From def92d1b8e9d373e2f6f27c366d578d97d8960c6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 15 May 2024 05:34:50 +0200 Subject: Merging upstream version 126.0. Signed-off-by: Daniel Baumann --- third_party/libwebrtc/pc/BUILD.gn | 155 +--- third_party/libwebrtc/pc/connection_context.cc | 7 +- third_party/libwebrtc/pc/connection_context.h | 8 - third_party/libwebrtc/pc/dtls_transport.cc | 34 +- third_party/libwebrtc/pc/dtls_transport.h | 18 +- .../libwebrtc/pc/jsep_session_description.cc | 36 +- third_party/libwebrtc/pc/legacy_stats_collector.cc | 63 +- third_party/libwebrtc/pc/legacy_stats_collector.h | 3 +- .../pc/legacy_stats_collector_unittest.cc | 4 +- third_party/libwebrtc/pc/media_session.cc | 52 +- third_party/libwebrtc/pc/media_session_unittest.cc | 74 ++ third_party/libwebrtc/pc/peer_connection.cc | 40 +- third_party/libwebrtc/pc/peer_connection.h | 3 - .../pc/peer_connection_crypto_unittest.cc | 11 +- .../peer_connection_encodings_integrationtest.cc | 29 +- .../pc/peer_connection_end_to_end_unittest.cc | 6 +- .../libwebrtc/pc/peer_connection_factory.cc | 10 +- third_party/libwebrtc/pc/peer_connection_factory.h | 5 +- .../pc/peer_connection_field_trial_tests.cc | 2 +- .../peer_connection_header_extension_unittest.cc | 3 +- .../pc/peer_connection_histogram_unittest.cc | 1 - .../pc/peer_connection_integrationtest.cc | 24 +- .../pc/peer_connection_interface_unittest.cc | 7 +- .../libwebrtc/pc/peer_connection_media_unittest.cc | 13 +- .../libwebrtc/pc/peer_connection_rampup_tests.cc | 8 +- .../libwebrtc/pc/peer_connection_rtp_unittest.cc | 37 +- .../pc/peer_connection_signaling_unittest.cc | 42 +- .../pc/peer_connection_simulcast_unittest.cc | 48 -- third_party/libwebrtc/pc/rtc_stats_collector.cc | 44 +- third_party/libwebrtc/pc/rtc_stats_collector.h | 5 - .../libwebrtc/pc/rtc_stats_collector_unittest.cc | 36 +- .../libwebrtc/pc/rtc_stats_integrationtest.cc | 866 +++++++++++---------- third_party/libwebrtc/pc/rtc_stats_traversal.cc | 2 +- third_party/libwebrtc/pc/rtp_transceiver.cc | 14 +- third_party/libwebrtc/pc/sctp_utils_unittest.cc | 8 +- third_party/libwebrtc/pc/sdp_offer_answer.cc | 27 +- .../libwebrtc/pc/sdp_offer_answer_unittest.cc | 119 +++ third_party/libwebrtc/pc/session_description.h | 26 +- .../libwebrtc/pc/test/integration_test_helpers.cc | 1 - .../libwebrtc/pc/test/integration_test_helpers.h | 11 +- third_party/libwebrtc/pc/test/svc_e2e_tests.cc | 9 +- third_party/libwebrtc/pc/webrtc_sdp.cc | 114 +-- third_party/libwebrtc/pc/webrtc_sdp.h | 2 +- third_party/libwebrtc/pc/webrtc_sdp_unittest.cc | 131 +++- 44 files changed, 1110 insertions(+), 1048 deletions(-) (limited to 'third_party/libwebrtc/pc') diff --git a/third_party/libwebrtc/pc/BUILD.gn b/third_party/libwebrtc/pc/BUILD.gn index e9549cdfd8..e351748485 100644 --- a/third_party/libwebrtc/pc/BUILD.gn +++ b/third_party/libwebrtc/pc/BUILD.gn @@ -16,7 +16,6 @@ # - rtc_pc # - session_description # - simulcast_description -# - peerconnection # - sdp_utils # - media_stream_observer # - video_track_source @@ -736,143 +735,6 @@ rtc_library("media_protocol_names") { absl_deps = [ "//third_party/abseil-cpp/absl/strings" ] } -rtc_source_set("peerconnection") { - # TODO(bugs.webrtc.org/13661): Reduce visibility if possible - visibility = [ "*" ] # Used by Chromium and others - allow_poison = [ "environment_construction" ] - cflags = [] - sources = [] - - deps = [ - ":audio_rtp_receiver", - ":audio_track", - ":connection_context", - ":data_channel_controller", - ":data_channel_utils", - ":dtmf_sender", - ":ice_server_parsing", - ":jitter_buffer_delay", - ":jsep_ice_candidate", - ":jsep_session_description", - ":legacy_stats_collector", - ":legacy_stats_collector_interface", - ":local_audio_source", - ":media_protocol_names", - ":media_stream", - ":media_stream_observer", - ":peer_connection", - ":peer_connection_factory", - ":peer_connection_internal", - ":peer_connection_message_handler", - ":proxy", - ":remote_audio_source", - ":rtc_stats_collector", - ":rtc_stats_traversal", - ":rtp_parameters_conversion", - ":rtp_receiver", - ":rtp_sender", - ":rtp_transceiver", - ":rtp_transmission_manager", - ":sctp_data_channel", - ":sdp_offer_answer", - ":sdp_state_provider", - ":sdp_utils", - ":session_description", - ":simulcast_description", - ":simulcast_sdp_serializer", - ":stream_collection", - ":track_media_info_map", - ":transceiver_list", - ":usage_pattern", - ":video_rtp_receiver", - ":video_track", - ":video_track_source", - ":webrtc_sdp", - ":webrtc_session_description_factory", - "../api:array_view", - "../api:async_dns_resolver", - "../api:audio_options_api", - "../api:call_api", - "../api:callfactory_api", - "../api:fec_controller_api", - "../api:field_trials_view", - "../api:frame_transformer_interface", - "../api:ice_transport_factory", - "../api:libjingle_logging_api", - "../api:libjingle_peerconnection_api", - "../api:media_stream_interface", - "../api:network_state_predictor_api", - "../api:packet_socket_factory", - "../api:priority", - "../api:rtc_error", - "../api:rtc_event_log_output_file", - "../api:rtc_stats_api", - "../api:rtp_parameters", - "../api:rtp_transceiver_direction", - "../api:scoped_refptr", - "../api:sequence_checker", - "../api/adaptation:resource_adaptation_api", - "../api/audio_codecs:audio_codecs_api", - "../api/crypto:frame_decryptor_interface", - "../api/crypto:options", - "../api/neteq:neteq_api", - "../api/rtc_event_log", - "../api/task_queue", - "../api/task_queue:pending_task_safety_flag", - "../api/transport:bitrate_settings", - "../api/transport:datagram_transport_interface", - "../api/transport:enums", - "../api/transport:field_trial_based_config", - "../api/transport:network_control", - "../api/transport:sctp_transport_factory_interface", - "../api/units:data_rate", - "../api/video:builtin_video_bitrate_allocator_factory", - "../api/video:video_bitrate_allocator_factory", - "../api/video:video_codec_constants", - "../api/video:video_frame", - "../api/video:video_rtp_headers", - "../api/video_codecs:video_codecs_api", - "../call:call_interfaces", - "../call:rtp_interfaces", - "../call:rtp_sender", - "../common_video", - "../logging:ice_log", - "../media:rtc_data_sctp_transport_internal", - "../media:rtc_media_base", - "../media:rtc_media_config", - "../modules/audio_processing:audio_processing_statistics", - "../modules/rtp_rtcp:rtp_rtcp_format", - "../p2p:rtc_p2p", - "../rtc_base:callback_list", - "../rtc_base:checks", - "../rtc_base:ip_address", - "../rtc_base:network_constants", - "../rtc_base:rtc_operations_chain", - "../rtc_base:safe_minmax", - "../rtc_base:socket_address", - "../rtc_base:threading", - "../rtc_base:weak_ptr", - "../rtc_base/experiments:field_trial_parser", - "../rtc_base/network:sent_packet", - "../rtc_base/synchronization:mutex", - "../rtc_base/system:file_wrapper", - "../rtc_base/system:no_unique_address", - "../rtc_base/system:rtc_export", - "../rtc_base/system:unused", - "../rtc_base/third_party/base64", - "../rtc_base/third_party/sigslot", - "../stats", - "../system_wrappers", - "../system_wrappers:field_trial", - "../system_wrappers:metrics", - ] - absl_deps = [ - "//third_party/abseil-cpp/absl/algorithm:container", - "//third_party/abseil-cpp/absl/strings", - "//third_party/abseil-cpp/absl/types:optional", - ] -} - rtc_library("sctp_data_channel") { visibility = [ ":*" ] sources = [ @@ -930,8 +792,6 @@ rtc_library("connection_context") { ] deps = [ ":media_factory", - "../api:callfactory_api", - "../api:field_trials_view", "../api:libjingle_peerconnection_api", "../api:media_stream_interface", "../api:refcountedbase", @@ -939,7 +799,6 @@ rtc_library("connection_context") { "../api:sequence_checker", "../api/environment", "../api/neteq:neteq_api", - "../api/transport:field_trial_based_config", "../api/transport:sctp_transport_factory_interface", "../media:rtc_data_sctp_transport_factory", "../media:rtc_media_base", @@ -1512,7 +1371,6 @@ rtc_source_set("peer_connection_factory") { ":peer_connection_factory_proxy", ":peer_connection_proxy", "../api:audio_options_api", - "../api:callfactory_api", "../api:fec_controller_api", "../api:field_trials_view", "../api:ice_transport_interface", @@ -2064,14 +1922,19 @@ rtc_source_set("legacy_stats_collector_interface") { ] } +# This target contains the libraries that are required in order to get an +# usable peerconnection-using binary. rtc_source_set("libjingle_peerconnection") { # TODO(bugs.webrtc.org/13661): Reduce visibility if possible visibility = [ "*" ] # Used by Chrome and others allow_poison = [ "environment_construction" ] deps = [ - ":peerconnection", + ":jsep_session_description", + ":peer_connection_factory", + ":rtc_stats_collector", "../api:libjingle_peerconnection_api", + "../stats", ] } @@ -2119,7 +1982,6 @@ if (rtc_include_tests && !build_with_chromium) { ":media_protocol_names", ":media_session", ":pc_test_utils", - ":peerconnection", ":rtc_pc", ":rtcp_mux_filter", ":rtp_media_utils", @@ -2220,7 +2082,6 @@ if (rtc_include_tests && !build_with_chromium) { deps = [ ":pc_test_utils", ":peer_connection", - ":peerconnection", ":peerconnection_wrapper", "../api:audio_options_api", "../api:create_peerconnection_factory", @@ -2273,7 +2134,6 @@ if (rtc_include_tests && !build_with_chromium) { ] deps = [ ":pc_test_utils", - ":peerconnection", ":sdp_utils", "../api:function_view", "../api:libjingle_peerconnection_api", @@ -2419,7 +2279,6 @@ if (rtc_include_tests && !build_with_chromium) { ":webrtc_sdp", "../api:array_view", "../api:audio_options_api", - "../api:callfactory_api", "../api:candidate", "../api:create_peerconnection_factory", "../api:dtls_transport_interface", @@ -2632,7 +2491,6 @@ if (rtc_include_tests && !build_with_chromium) { ":peer_connection", ":peer_connection_factory", ":peer_connection_proxy", - ":peerconnection", ":remote_audio_source", ":rtp_media_utils", ":rtp_parameters_conversion", @@ -2791,7 +2649,6 @@ if (rtc_include_tests && !build_with_chromium) { ":jitter_buffer_delay", ":libjingle_peerconnection", ":peer_connection_internal", - ":peerconnection", ":rtp_receiver", ":rtp_sender", ":sctp_data_channel", diff --git a/third_party/libwebrtc/pc/connection_context.cc b/third_party/libwebrtc/pc/connection_context.cc index df4522bf13..56a6e91869 100644 --- a/third_party/libwebrtc/pc/connection_context.cc +++ b/third_party/libwebrtc/pc/connection_context.cc @@ -15,7 +15,6 @@ #include #include "api/environment/environment.h" -#include "api/transport/field_trial_based_config.h" #include "media/base/media_engine.h" #include "media/sctp/sctp_transport_factory.h" #include "pc/media_factory.h" @@ -63,8 +62,7 @@ rtc::Thread* MaybeWrapThread(rtc::Thread* signaling_thread, std::unique_ptr MaybeCreateSctpFactory( std::unique_ptr factory, - rtc::Thread* network_thread, - const FieldTrialsView& field_trials) { + rtc::Thread* network_thread) { if (factory) { return factory; } @@ -113,8 +111,7 @@ ConnectionContext::ConnectionContext( default_socket_factory_(std::move(dependencies->packet_socket_factory)), sctp_factory_( MaybeCreateSctpFactory(std::move(dependencies->sctp_factory), - network_thread(), - env_.field_trials())), + network_thread())), use_rtx_(true) { RTC_DCHECK_RUN_ON(signaling_thread_); RTC_DCHECK(!(default_network_manager_ && network_monitor_factory_)) diff --git a/third_party/libwebrtc/pc/connection_context.h b/third_party/libwebrtc/pc/connection_context.h index 893a3b0e52..28b2d1cdd5 100644 --- a/third_party/libwebrtc/pc/connection_context.h +++ b/third_party/libwebrtc/pc/connection_context.h @@ -14,9 +14,7 @@ #include #include -#include "api/call/call_factory_interface.h" #include "api/environment/environment.h" -#include "api/field_trials_view.h" #include "api/media_stream_interface.h" #include "api/peer_connection_interface.h" #include "api/ref_counted_base.h" @@ -81,12 +79,6 @@ class ConnectionContext final // but they are not supposed to change after creating the PeerConnection. const Environment& env() const { return env_; } - // Field trials associated with the PeerConnectionFactory. - // Note: that there can be different field trials for different - // PeerConnections (but they are not supposed change after creating the - // PeerConnection). - const FieldTrialsView& field_trials() const { return env_.field_trials(); } - // Accessors only used from the PeerConnectionFactory class rtc::NetworkManager* default_network_manager() { RTC_DCHECK_RUN_ON(signaling_thread_); diff --git a/third_party/libwebrtc/pc/dtls_transport.cc b/third_party/libwebrtc/pc/dtls_transport.cc index 15eed9e47b..4888d9f9e7 100644 --- a/third_party/libwebrtc/pc/dtls_transport.cc +++ b/third_party/libwebrtc/pc/dtls_transport.cc @@ -41,8 +41,18 @@ DtlsTransport::DtlsTransport( } DtlsTransport::~DtlsTransport() { + // TODO(tommi): Due to a reference being held by the RtpSenderBase + // implementation, the last reference to the `DtlsTransport` instance can + // be released on the signaling thread. + // RTC_DCHECK_RUN_ON(owner_thread_); + // We depend on the signaling thread to call Clear() before dropping // its last reference to this object. + + // If there are non `owner_thread_` references outstanding, and those + // references are the last ones released, we depend on Clear() having been + // called from the owner_thread before the last reference is deleted. + // `Clear()` is currently called from `JsepTransport::~JsepTransport`. RTC_DCHECK(owner_thread_->IsCurrent() || !internal_dtls_transport_); } @@ -72,14 +82,8 @@ void DtlsTransport::Clear() { RTC_DCHECK(internal()); bool must_send_event = (internal()->dtls_state() != DtlsTransportState::kClosed); - // The destructor of cricket::DtlsTransportInternal calls back - // into DtlsTransport, so we can't hold the lock while releasing. - std::unique_ptr transport_to_release; - { - MutexLock lock(&lock_); - transport_to_release = std::move(internal_dtls_transport_); - ice_transport_->Clear(); - } + internal_dtls_transport_.reset(); + ice_transport_->Clear(); UpdateInformation(); if (observer_ && must_send_event) { observer_->OnStateChange(Information()); @@ -100,7 +104,6 @@ void DtlsTransport::OnInternalDtlsState( void DtlsTransport::UpdateInformation() { RTC_DCHECK_RUN_ON(owner_thread_); - MutexLock lock(&lock_); if (internal_dtls_transport_) { if (internal_dtls_transport_->dtls_state() == DtlsTransportState::kConnected) { @@ -125,23 +128,24 @@ void DtlsTransport::UpdateInformation() { success &= internal_dtls_transport_->GetSslCipherSuite(&ssl_cipher_suite); success &= internal_dtls_transport_->GetSrtpCryptoSuite(&srtp_cipher); if (success) { - info_ = DtlsTransportInformation( + set_info(DtlsTransportInformation( internal_dtls_transport_->dtls_state(), role, tls_version, ssl_cipher_suite, srtp_cipher, - internal_dtls_transport_->GetRemoteSSLCertChain()); + internal_dtls_transport_->GetRemoteSSLCertChain())); } else { RTC_LOG(LS_ERROR) << "DtlsTransport in connected state has incomplete " "TLS information"; - info_ = DtlsTransportInformation( + set_info(DtlsTransportInformation( internal_dtls_transport_->dtls_state(), role, absl::nullopt, absl::nullopt, absl::nullopt, - internal_dtls_transport_->GetRemoteSSLCertChain()); + internal_dtls_transport_->GetRemoteSSLCertChain())); } } else { - info_ = DtlsTransportInformation(internal_dtls_transport_->dtls_state()); + set_info( + DtlsTransportInformation(internal_dtls_transport_->dtls_state())); } } else { - info_ = DtlsTransportInformation(DtlsTransportState::kClosed); + set_info(DtlsTransportInformation(DtlsTransportState::kClosed)); } } diff --git a/third_party/libwebrtc/pc/dtls_transport.h b/third_party/libwebrtc/pc/dtls_transport.h index cca4cc980a..a1893297e6 100644 --- a/third_party/libwebrtc/pc/dtls_transport.h +++ b/third_party/libwebrtc/pc/dtls_transport.h @@ -12,6 +12,7 @@ #define PC_DTLS_TRANSPORT_H_ #include +#include #include "api/dtls_transport_interface.h" #include "api/ice_transport_interface.h" @@ -40,18 +41,22 @@ class DtlsTransport : public DtlsTransportInterface { std::unique_ptr internal); rtc::scoped_refptr ice_transport() override; + + // Currently called from the signaling thread and potentially Chromium's + // JS thread. DtlsTransportInformation Information() override; + void RegisterObserver(DtlsTransportObserverInterface* observer) override; void UnregisterObserver() override; void Clear(); cricket::DtlsTransportInternal* internal() { - MutexLock lock(&lock_); + RTC_DCHECK_RUN_ON(owner_thread_); return internal_dtls_transport_.get(); } const cricket::DtlsTransportInternal* internal() const { - MutexLock lock(&lock_); + RTC_DCHECK_RUN_ON(owner_thread_); return internal_dtls_transport_.get(); } @@ -63,12 +68,19 @@ class DtlsTransport : public DtlsTransportInterface { DtlsTransportState state); void UpdateInformation(); + // Called when changing `info_`. We only change the values from the + // `owner_thread_` (a.k.a. the network thread). + void set_info(DtlsTransportInformation&& info) RTC_RUN_ON(owner_thread_) { + MutexLock lock(&lock_); + info_ = std::move(info); + } + DtlsTransportObserverInterface* observer_ = nullptr; rtc::Thread* owner_thread_; mutable Mutex lock_; DtlsTransportInformation info_ RTC_GUARDED_BY(lock_); std::unique_ptr internal_dtls_transport_ - RTC_GUARDED_BY(lock_); + RTC_GUARDED_BY(owner_thread_); const rtc::scoped_refptr ice_transport_; }; diff --git a/third_party/libwebrtc/pc/jsep_session_description.cc b/third_party/libwebrtc/pc/jsep_session_description.cc index 885c1eb310..7fae4459ec 100644 --- a/third_party/libwebrtc/pc/jsep_session_description.cc +++ b/third_party/libwebrtc/pc/jsep_session_description.cc @@ -26,37 +26,15 @@ #include "rtc_base/net_helper.h" #include "rtc_base/socket_address.h" +using cricket::Candidate; using cricket::SessionDescription; namespace webrtc { namespace { -// RFC 5245 -// It is RECOMMENDED that default candidates be chosen based on the -// likelihood of those candidates to work with the peer that is being -// contacted. It is RECOMMENDED that relayed > reflexive > host. -constexpr int kPreferenceUnknown = 0; -constexpr int kPreferenceHost = 1; -constexpr int kPreferenceReflexive = 2; -constexpr int kPreferenceRelayed = 3; - constexpr char kDummyAddress[] = "0.0.0.0"; constexpr int kDummyPort = 9; -int GetCandidatePreferenceFromType(const std::string& type) { - int preference = kPreferenceUnknown; - if (type == cricket::LOCAL_PORT_TYPE) { - preference = kPreferenceHost; - } else if (type == cricket::STUN_PORT_TYPE) { - preference = kPreferenceReflexive; - } else if (type == cricket::RELAY_PORT_TYPE) { - preference = kPreferenceRelayed; - } else { - preference = kPreferenceUnknown; - } - return preference; -} - // Update the connection address for the MediaContentDescription based on the // candidates. void UpdateConnectionAddress( @@ -65,7 +43,7 @@ void UpdateConnectionAddress( int port = kDummyPort; std::string ip = kDummyAddress; std::string hostname; - int current_preference = kPreferenceUnknown; + int current_preference = 0; // Start with lowest preference. int current_family = AF_UNSPEC; for (size_t i = 0; i < candidate_collection.count(); ++i) { const IceCandidateInterface* jsep_candidate = candidate_collection.at(i); @@ -77,8 +55,7 @@ void UpdateConnectionAddress( if (jsep_candidate->candidate().protocol() != cricket::UDP_PROTOCOL_NAME) { continue; } - const int preference = - GetCandidatePreferenceFromType(jsep_candidate->candidate().type()); + const int preference = jsep_candidate->candidate().type_preference(); const int family = jsep_candidate->candidate().address().ipaddr().family(); // See if this candidate is more preferable then the current one if it's the // same family. Or if the current family is IPv4 already so we could safely @@ -253,7 +230,7 @@ bool JsepSessionDescription::AddCandidate( return false; } - cricket::Candidate updated_candidate = candidate->candidate(); + Candidate updated_candidate = candidate->candidate(); if (updated_candidate.username().empty()) { updated_candidate.set_username(transport_info->description.ice_ufrag); } @@ -278,7 +255,7 @@ bool JsepSessionDescription::AddCandidate( } size_t JsepSessionDescription::RemoveCandidates( - const std::vector& candidates) { + const std::vector& candidates) { size_t num_removed = 0; for (auto& candidate : candidates) { int mediasection_index = GetMediasectionIndex(candidate); @@ -352,8 +329,7 @@ bool JsepSessionDescription::GetMediasectionIndex( return true; } -int JsepSessionDescription::GetMediasectionIndex( - const cricket::Candidate& candidate) { +int JsepSessionDescription::GetMediasectionIndex(const Candidate& candidate) { // Find the description with a matching transport name of the candidate. const std::string& transport_name = candidate.transport_name(); for (size_t i = 0; i < description_->contents().size(); ++i) { diff --git a/third_party/libwebrtc/pc/legacy_stats_collector.cc b/third_party/libwebrtc/pc/legacy_stats_collector.cc index 98b7cb9677..135829abc9 100644 --- a/third_party/libwebrtc/pc/legacy_stats_collector.cc +++ b/third_party/libwebrtc/pc/legacy_stats_collector.cc @@ -188,9 +188,10 @@ void ExtractStats(const cricket::VoiceReceiverInfo& info, {StatsReport::kStatsValueNameAccelerateRate, info.accelerate_rate}, {StatsReport::kStatsValueNamePreemptiveExpandRate, info.preemptive_expand_rate}, - {StatsReport::kStatsValueNameTotalAudioEnergy, info.total_output_energy}, + {StatsReport::kStatsValueNameTotalAudioEnergy, + static_cast(info.total_output_energy)}, {StatsReport::kStatsValueNameTotalSamplesDuration, - info.total_output_duration}}; + static_cast(info.total_output_duration)}}; const IntForAdd ints[] = { {StatsReport::kStatsValueNameCurrentDelayMs, info.delay_estimate_ms}, @@ -244,9 +245,10 @@ void ExtractStats(const cricket::VoiceSenderInfo& info, SetAudioProcessingStats(report, info.apm_statistics); const FloatForAdd floats[] = { - {StatsReport::kStatsValueNameTotalAudioEnergy, info.total_input_energy}, + {StatsReport::kStatsValueNameTotalAudioEnergy, + static_cast(info.total_input_energy)}, {StatsReport::kStatsValueNameTotalSamplesDuration, - info.total_input_duration}}; + static_cast(info.total_input_duration)}}; RTC_DCHECK_GE(info.audio_level, 0); const IntForAdd ints[] = { @@ -340,7 +342,8 @@ void ExtractStats(const cricket::VideoReceiverInfo& info, {StatsReport::kStatsValueNamePlisSent, info.plis_sent}, {StatsReport::kStatsValueNameRenderDelayMs, info.render_delay_ms}, {StatsReport::kStatsValueNameTargetDelayMs, info.target_delay_ms}, - {StatsReport::kStatsValueNameFramesDecoded, info.frames_decoded}, + {StatsReport::kStatsValueNameFramesDecoded, + static_cast(info.frames_decoded)}, }; for (const auto& i : ints) @@ -383,15 +386,19 @@ void ExtractStats(const cricket::VideoSenderInfo& info, info.encode_usage_percent}, {StatsReport::kStatsValueNameFirsReceived, info.firs_received}, {StatsReport::kStatsValueNameFrameHeightSent, info.send_frame_height}, - {StatsReport::kStatsValueNameFrameRateInput, round(info.framerate_input)}, + {StatsReport::kStatsValueNameFrameRateInput, + static_cast(round(info.framerate_input))}, {StatsReport::kStatsValueNameFrameRateSent, info.framerate_sent}, {StatsReport::kStatsValueNameFrameWidthSent, info.send_frame_width}, - {StatsReport::kStatsValueNameNacksReceived, info.nacks_received}, + {StatsReport::kStatsValueNameNacksReceived, + static_cast(info.nacks_received)}, {StatsReport::kStatsValueNamePacketsLost, info.packets_lost}, {StatsReport::kStatsValueNamePacketsSent, info.packets_sent}, {StatsReport::kStatsValueNamePlisReceived, info.plis_received}, - {StatsReport::kStatsValueNameFramesEncoded, info.frames_encoded}, - {StatsReport::kStatsValueNameHugeFramesSent, info.huge_frames_sent}, + {StatsReport::kStatsValueNameFramesEncoded, + static_cast(info.frames_encoded)}, + {StatsReport::kStatsValueNameHugeFramesSent, + static_cast(info.huge_frames_sent)}, }; for (const auto& i : ints) @@ -489,17 +496,17 @@ void ExtractStatsFromList( } // namespace -const char* IceCandidateTypeToStatsType(const std::string& candidate_type) { - if (candidate_type == cricket::LOCAL_PORT_TYPE) { +const char* IceCandidateTypeToStatsType(const cricket::Candidate& candidate) { + if (candidate.is_local()) { return STATSREPORT_LOCAL_PORT_TYPE; } - if (candidate_type == cricket::STUN_PORT_TYPE) { + if (candidate.is_stun()) { return STATSREPORT_STUN_PORT_TYPE; } - if (candidate_type == cricket::PRFLX_PORT_TYPE) { + if (candidate.is_prflx()) { return STATSREPORT_PRFLX_PORT_TYPE; } - if (candidate_type == cricket::RELAY_PORT_TYPE) { + if (candidate.is_relay()) { return STATSREPORT_RELAY_PORT_TYPE; } RTC_DCHECK_NOTREACHED(); @@ -778,19 +785,25 @@ StatsReport* LegacyStatsCollector::AddConnectionInfoReport( AddCandidateReport(remote_candidate_stats, false)->id()); const Int64ForAdd int64s[] = { - {StatsReport::kStatsValueNameBytesReceived, info.recv_total_bytes}, - {StatsReport::kStatsValueNameBytesSent, info.sent_total_bytes}, - {StatsReport::kStatsValueNamePacketsSent, info.sent_total_packets}, - {StatsReport::kStatsValueNameRtt, info.rtt}, + {StatsReport::kStatsValueNameBytesReceived, + static_cast(info.recv_total_bytes)}, + {StatsReport::kStatsValueNameBytesSent, + static_cast(info.sent_total_bytes)}, + {StatsReport::kStatsValueNamePacketsSent, + static_cast(info.sent_total_packets)}, + {StatsReport::kStatsValueNameRtt, static_cast(info.rtt)}, {StatsReport::kStatsValueNameSendPacketsDiscarded, - info.sent_discarded_packets}, + static_cast(info.sent_discarded_packets)}, {StatsReport::kStatsValueNameSentPingRequestsTotal, - info.sent_ping_requests_total}, + static_cast(info.sent_ping_requests_total)}, {StatsReport::kStatsValueNameSentPingRequestsBeforeFirstResponse, - info.sent_ping_requests_before_first_response}, - {StatsReport::kStatsValueNameSentPingResponses, info.sent_ping_responses}, - {StatsReport::kStatsValueNameRecvPingRequests, info.recv_ping_requests}, - {StatsReport::kStatsValueNameRecvPingResponses, info.recv_ping_responses}, + static_cast(info.sent_ping_requests_before_first_response)}, + {StatsReport::kStatsValueNameSentPingResponses, + static_cast(info.sent_ping_responses)}, + {StatsReport::kStatsValueNameRecvPingRequests, + static_cast(info.recv_ping_requests)}, + {StatsReport::kStatsValueNameRecvPingResponses, + static_cast(info.recv_ping_responses)}, }; for (const auto& i : int64s) report->AddInt64(i.name, i.value); @@ -831,7 +844,7 @@ StatsReport* LegacyStatsCollector::AddCandidateReport( report->AddInt(StatsReport::kStatsValueNameCandidatePriority, candidate.priority()); report->AddString(StatsReport::kStatsValueNameCandidateType, - IceCandidateTypeToStatsType(candidate.type())); + IceCandidateTypeToStatsType(candidate)); report->AddString(StatsReport::kStatsValueNameCandidateTransportType, candidate.protocol()); } diff --git a/third_party/libwebrtc/pc/legacy_stats_collector.h b/third_party/libwebrtc/pc/legacy_stats_collector.h index 1c7aad0636..e0371638ee 100644 --- a/third_party/libwebrtc/pc/legacy_stats_collector.h +++ b/third_party/libwebrtc/pc/legacy_stats_collector.h @@ -26,6 +26,7 @@ #include #include "absl/types/optional.h" +#include "api/candidate.h" #include "api/field_trials_view.h" #include "api/legacy_stats_types.h" #include "api/media_stream_interface.h" @@ -45,7 +46,7 @@ namespace webrtc { // Conversion function to convert candidate type string to the corresponding one // from enum RTCStatsIceCandidateType. -const char* IceCandidateTypeToStatsType(const std::string& candidate_type); +const char* IceCandidateTypeToStatsType(const cricket::Candidate& candidate); // Conversion function to convert adapter type to report string which are more // fitting to the general style of http://w3c.github.io/webrtc-stats. This is diff --git a/third_party/libwebrtc/pc/legacy_stats_collector_unittest.cc b/third_party/libwebrtc/pc/legacy_stats_collector_unittest.cc index 3099d1188a..5f6140da54 100644 --- a/third_party/libwebrtc/pc/legacy_stats_collector_unittest.cc +++ b/third_party/libwebrtc/pc/legacy_stats_collector_unittest.cc @@ -1391,7 +1391,7 @@ TEST_F(LegacyStatsCollectorTest, IceCandidateReport) { ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports, StatsReport::kStatsValueNameCandidatePriority)); EXPECT_EQ( - IceCandidateTypeToStatsType(cricket::LOCAL_PORT_TYPE), + IceCandidateTypeToStatsType(local), ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports, StatsReport::kStatsValueNameCandidateType)); EXPECT_EQ( @@ -1421,7 +1421,7 @@ TEST_F(LegacyStatsCollectorTest, IceCandidateReport) { reports, StatsReport::kStatsValueNameCandidatePriority)); EXPECT_EQ( - IceCandidateTypeToStatsType(cricket::PRFLX_PORT_TYPE), + IceCandidateTypeToStatsType(remote), ExtractStatsValue(StatsReport::kStatsReportTypeIceRemoteCandidate, reports, StatsReport::kStatsValueNameCandidateType)); EXPECT_EQ(kNotFound, diff --git a/third_party/libwebrtc/pc/media_session.cc b/third_party/libwebrtc/pc/media_session.cc index 573e35225e..a118beebb0 100644 --- a/third_party/libwebrtc/pc/media_session.cc +++ b/third_party/libwebrtc/pc/media_session.cc @@ -728,6 +728,16 @@ void NegotiatePacketization(const Codec& local_codec, : absl::nullopt; } +#ifdef RTC_ENABLE_H265 +void NegotiateTxMode(const Codec& local_codec, + const Codec& remote_codec, + Codec* negotiated_codec) { + negotiated_codec->tx_mode = (local_codec.tx_mode == remote_codec.tx_mode) + ? local_codec.tx_mode + : absl::nullopt; +} +#endif + // Finds a codec in `codecs2` that matches `codec_to_match`, which is // a member of `codecs1`. If `codec_to_match` is an RED or RTX codec, both // the codecs themselves and their associated codecs must match. @@ -849,6 +859,13 @@ void NegotiateCodecs(const std::vector& local_codecs, webrtc::H264GenerateProfileLevelIdForAnswer(ours.params, theirs->params, &negotiated.params); } +#ifdef RTC_ENABLE_H265 + if (absl::EqualsIgnoreCase(ours.name, kH265CodecName)) { + webrtc::H265GenerateProfileTierLevelForAnswer( + ours.params, theirs->params, &negotiated.params); + NegotiateTxMode(ours, *theirs, &negotiated); + } +#endif negotiated.id = theirs->id; negotiated.name = theirs->name; negotiated_codecs->push_back(std::move(negotiated)); @@ -1864,11 +1881,13 @@ MediaSessionDescriptionFactory::CreateOfferOrError( // Be conservative and signal using both a=msid and a=ssrc lines. Unified // Plan answerers will look at a=msid and Plan B answerers will look at the // a=ssrc MSID line. - offer->set_msid_signaling(cricket::kMsidSignalingMediaSection | + offer->set_msid_signaling(cricket::kMsidSignalingSemantic | + cricket::kMsidSignalingMediaSection | cricket::kMsidSignalingSsrcAttribute); } else { // Plan B always signals MSID using a=ssrc lines. - offer->set_msid_signaling(cricket::kMsidSignalingSsrcAttribute); + offer->set_msid_signaling(cricket::kMsidSignalingSemantic | + cricket::kMsidSignalingSsrcAttribute); } offer->set_extmap_allow_mixed(session_options.offer_extmap_allow_mixed); @@ -2041,7 +2060,16 @@ MediaSessionDescriptionFactory::CreateAnswerOrError( if (is_unified_plan_) { // Unified Plan needs to look at what the offer included to find the most // compatible answer. - if (offer->msid_signaling() == 0) { + int msid_signaling = offer->msid_signaling(); + if (msid_signaling == + (cricket::kMsidSignalingSemantic | cricket::kMsidSignalingMediaSection | + cricket::kMsidSignalingSsrcAttribute)) { + // If both a=msid and a=ssrc MSID signaling methods were used, we're + // probably talking to a Unified Plan endpoint so respond with just + // a=msid. + answer->set_msid_signaling(cricket::kMsidSignalingSemantic | + cricket::kMsidSignalingMediaSection); + } else if (msid_signaling == cricket::kMsidSignalingSemantic) { // We end up here in one of three cases: // 1. An empty offer. We'll reply with an empty answer so it doesn't // matter what we pick here. @@ -2050,23 +2078,19 @@ MediaSessionDescriptionFactory::CreateAnswerOrError( // 3. Media that's either sendonly or inactive from the remote endpoint. // We don't have any information to say whether the endpoint is Plan B // or Unified Plan, so be conservative and send both. - answer->set_msid_signaling(cricket::kMsidSignalingMediaSection | + answer->set_msid_signaling(cricket::kMsidSignalingSemantic | + cricket::kMsidSignalingMediaSection | cricket::kMsidSignalingSsrcAttribute); - } else if (offer->msid_signaling() == - (cricket::kMsidSignalingMediaSection | - cricket::kMsidSignalingSsrcAttribute)) { - // If both a=msid and a=ssrc MSID signaling methods were used, we're - // probably talking to a Unified Plan endpoint so respond with just - // a=msid. - answer->set_msid_signaling(cricket::kMsidSignalingMediaSection); } else { // Otherwise, it's clear which method the offerer is using so repeat that - // back to them. - answer->set_msid_signaling(offer->msid_signaling()); + // back to them. This includes the case where the msid-semantic line is + // not included. + answer->set_msid_signaling(msid_signaling); } } else { // Plan B always signals MSID using a=ssrc lines. - answer->set_msid_signaling(cricket::kMsidSignalingSsrcAttribute); + answer->set_msid_signaling(cricket::kMsidSignalingSemantic | + cricket::kMsidSignalingSsrcAttribute); } return answer; diff --git a/third_party/libwebrtc/pc/media_session_unittest.cc b/third_party/libwebrtc/pc/media_session_unittest.cc index 641f638e72..f4fd09cba0 100644 --- a/third_party/libwebrtc/pc/media_session_unittest.cc +++ b/third_party/libwebrtc/pc/media_session_unittest.cc @@ -4323,6 +4323,80 @@ TEST_F(MediaSessionDescriptionFactoryTest, EXPECT_EQ(vcd1->codecs()[0].id, vcd2->codecs()[0].id); } +#ifdef RTC_ENABLE_H265 +// Test verifying that negotiating codecs with the same tx-mode retains the +// tx-mode value. +TEST_F(MediaSessionDescriptionFactoryTest, H265TxModeIsEqualRetainIt) { + std::vector f1_codecs = {CreateVideoCodec(96, "H265")}; + f1_codecs.back().tx_mode = "mrst"; + f1_.set_video_codecs(f1_codecs, f1_codecs); + + std::vector f2_codecs = {CreateVideoCodec(96, "H265")}; + f2_codecs.back().tx_mode = "mrst"; + f2_.set_video_codecs(f2_codecs, f2_codecs); + + MediaSessionOptions opts; + AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video1", + RtpTransceiverDirection::kSendRecv, kActive, + &opts); + + // Create an offer with two video sections using same codecs. + std::unique_ptr offer = + f1_.CreateOfferOrError(opts, nullptr).MoveValue(); + ASSERT_TRUE(offer); + ASSERT_EQ(1u, offer->contents().size()); + const MediaContentDescription* vcd1 = + offer->contents()[0].media_description(); + ASSERT_EQ(1u, vcd1->codecs().size()); + EXPECT_EQ(vcd1->codecs()[0].tx_mode, "mrst"); + + // Create answer and negotiate the codecs. + std::unique_ptr answer = + f2_.CreateAnswerOrError(offer.get(), opts, nullptr).MoveValue(); + ASSERT_TRUE(answer); + ASSERT_EQ(1u, answer->contents().size()); + vcd1 = answer->contents()[0].media_description(); + ASSERT_EQ(1u, vcd1->codecs().size()); + EXPECT_EQ(vcd1->codecs()[0].tx_mode, "mrst"); +} + +// Test verifying that negotiating codecs with different tx_mode removes +// the tx_mode value. +TEST_F(MediaSessionDescriptionFactoryTest, H265TxModeIsDifferentDropCodecs) { + std::vector f1_codecs = {CreateVideoCodec(96, "H265")}; + f1_codecs.back().tx_mode = "mrst"; + f1_.set_video_codecs(f1_codecs, f1_codecs); + + std::vector f2_codecs = {CreateVideoCodec(96, "H265")}; + f2_codecs.back().tx_mode = "mrmt"; + f2_.set_video_codecs(f2_codecs, f2_codecs); + + MediaSessionOptions opts; + AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video1", + RtpTransceiverDirection::kSendRecv, kActive, + &opts); + + // Create an offer with two video sections using same codecs. + std::unique_ptr offer = + f1_.CreateOfferOrError(opts, nullptr).MoveValue(); + ASSERT_TRUE(offer); + ASSERT_EQ(1u, offer->contents().size()); + const VideoContentDescription* vcd1 = + offer->contents()[0].media_description()->as_video(); + ASSERT_EQ(1u, vcd1->codecs().size()); + EXPECT_EQ(vcd1->codecs()[0].tx_mode, "mrst"); + + // Create answer and negotiate the codecs. + std::unique_ptr answer = + f2_.CreateAnswerOrError(offer.get(), opts, nullptr).MoveValue(); + ASSERT_TRUE(answer); + ASSERT_EQ(1u, answer->contents().size()); + vcd1 = answer->contents()[0].media_description()->as_video(); + ASSERT_EQ(1u, vcd1->codecs().size()); + EXPECT_EQ(vcd1->codecs()[0].tx_mode, absl::nullopt); +} +#endif + // Test verifying that negotiating codecs with the same packetization retains // the packetization value. TEST_F(MediaSessionDescriptionFactoryTest, PacketizationIsEqual) { diff --git a/third_party/libwebrtc/pc/peer_connection.cc b/third_party/libwebrtc/pc/peer_connection.cc index 26b70c63db..8c9b0cbab6 100644 --- a/third_party/libwebrtc/pc/peer_connection.cc +++ b/third_party/libwebrtc/pc/peer_connection.cc @@ -78,19 +78,10 @@ using cricket::SimulcastLayerList; using cricket::StreamParams; using cricket::TransportInfo; -using cricket::LOCAL_PORT_TYPE; -using cricket::PRFLX_PORT_TYPE; -using cricket::RELAY_PORT_TYPE; -using cricket::STUN_PORT_TYPE; - namespace webrtc { namespace { -// UMA metric names. -const char kSimulcastNumberOfEncodings[] = - "WebRTC.PeerConnection.Simulcast.NumberOfSendEncodings"; - static const int REPORT_USAGE_PATTERN_DELAY_MS = 60000; uint32_t ConvertIceTransportTypeToCandidateFilter( @@ -115,10 +106,10 @@ IceCandidatePairType GetIceCandidatePairCounter( const cricket::Candidate& remote) { const auto& l = local.type(); const auto& r = remote.type(); - const auto& host = LOCAL_PORT_TYPE; - const auto& srflx = STUN_PORT_TYPE; - const auto& relay = RELAY_PORT_TYPE; - const auto& prflx = PRFLX_PORT_TYPE; + const auto& host = cricket::LOCAL_PORT_TYPE; + const auto& srflx = cricket::STUN_PORT_TYPE; + const auto& relay = cricket::RELAY_PORT_TYPE; + const auto& prflx = cricket::PRFLX_PORT_TYPE; if (l == host && r == host) { bool local_hostname = !local.address().hostname().empty() && local.address().IsUnresolvedIP(); @@ -1031,18 +1022,6 @@ PeerConnection::AddTransceiver( return AddTransceiver(track, RtpTransceiverInit()); } -RtpTransportInternal* PeerConnection::GetRtpTransport(const std::string& mid) { - // TODO(bugs.webrtc.org/9987): Avoid the thread jump. - // This might be done by caching the value on the signaling thread. - RTC_DCHECK_RUN_ON(signaling_thread()); - return network_thread()->BlockingCall([this, &mid] { - RTC_DCHECK_RUN_ON(network_thread()); - auto rtp_transport = transport_controller_->GetRtpTransport(mid); - RTC_DCHECK(rtp_transport); - return rtp_transport; - }); -} - RTCErrorOr> PeerConnection::AddTransceiver( rtc::scoped_refptr track, @@ -1112,9 +1091,6 @@ PeerConnection::AddTransceiver( : cricket::MEDIA_TYPE_VIDEO)); } - RTC_HISTOGRAM_COUNTS_LINEAR(kSimulcastNumberOfEncodings, - init.send_encodings.size(), 0, 7, 8); - size_t num_rids = absl::c_count_if(init.send_encodings, [](const RtpEncodingParameters& encoding) { return !encoding.rid.empty(); @@ -2095,10 +2071,8 @@ void PeerConnection::OnSelectedCandidatePairChanged( return; } - if (event.selected_candidate_pair.local_candidate().type() == - LOCAL_PORT_TYPE && - event.selected_candidate_pair.remote_candidate().type() == - LOCAL_PORT_TYPE) { + if (event.selected_candidate_pair.local_candidate().is_local() && + event.selected_candidate_pair.remote_candidate().is_local()) { NoteUsageEvent(UsageEvent::DIRECT_CONNECTION_SELECTED); } @@ -2806,7 +2780,7 @@ void PeerConnection::ReportBestConnectionState( // Increment the counter for IceCandidatePairType. if (local.protocol() == cricket::TCP_PROTOCOL_NAME || - (local.type() == RELAY_PORT_TYPE && + (local.is_relay() && local.relay_protocol() == cricket::TCP_PROTOCOL_NAME)) { RTC_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.CandidatePairType_TCP", GetIceCandidatePairCounter(local, remote), diff --git a/third_party/libwebrtc/pc/peer_connection.h b/third_party/libwebrtc/pc/peer_connection.h index e6037a2698..406bc1cef2 100644 --- a/third_party/libwebrtc/pc/peer_connection.h +++ b/third_party/libwebrtc/pc/peer_connection.h @@ -417,9 +417,6 @@ class PeerConnection : public PeerConnectionInternal, const RtpTransceiverInit& init, bool fire_callback = true) override; - // Returns rtp transport, result can not be nullptr. - RtpTransportInternal* GetRtpTransport(const std::string& mid); - // Returns true if SRTP (either using DTLS-SRTP or SDES) is required by // this session. bool SrtpRequired() const override; diff --git a/third_party/libwebrtc/pc/peer_connection_crypto_unittest.cc b/third_party/libwebrtc/pc/peer_connection_crypto_unittest.cc index a65988ab05..3b3f502e1f 100644 --- a/third_party/libwebrtc/pc/peer_connection_crypto_unittest.cc +++ b/third_party/libwebrtc/pc/peer_connection_crypto_unittest.cc @@ -55,6 +55,7 @@ #include "rtc_base/rtc_certificate_generator.h" #include "rtc_base/ssl_fingerprint.h" #include "rtc_base/thread.h" +#include "test/gmock.h" #include "test/gtest.h" #include "test/scoped_key_value_config.h" #ifdef WEBRTC_ANDROID @@ -70,6 +71,7 @@ namespace webrtc { using RTCConfiguration = PeerConnectionInterface::RTCConfiguration; using RTCOfferAnswerOptions = PeerConnectionInterface::RTCOfferAnswerOptions; using ::testing::Combine; +using ::testing::HasSubstr; using ::testing::Values; constexpr int kGenerateCertTimeout = 1000; @@ -789,16 +791,13 @@ TEST_P(PeerConnectionCryptoTest, SessionErrorIfFingerprintInvalid) { // Set the invalid answer and expect a fingerprint error. std::string error; ASSERT_FALSE(callee->SetLocalDescription(std::move(invalid_answer), &error)); - EXPECT_PRED_FORMAT2(AssertStringContains, error, - "Local fingerprint does not match identity."); + EXPECT_THAT(error, HasSubstr("Local fingerprint does not match identity.")); // Make sure that setting a valid remote offer or local answer also fails now. ASSERT_FALSE(callee->SetRemoteDescription(caller->CreateOffer(), &error)); - EXPECT_PRED_FORMAT2(AssertStringContains, error, - "Session error code: ERROR_CONTENT."); + EXPECT_THAT(error, HasSubstr("Session error code: ERROR_CONTENT.")); ASSERT_FALSE(callee->SetLocalDescription(std::move(valid_answer), &error)); - EXPECT_PRED_FORMAT2(AssertStringContains, error, - "Session error code: ERROR_CONTENT."); + EXPECT_THAT(error, HasSubstr("Session error code: ERROR_CONTENT.")); } INSTANTIATE_TEST_SUITE_P(PeerConnectionCryptoTest, diff --git a/third_party/libwebrtc/pc/peer_connection_encodings_integrationtest.cc b/third_party/libwebrtc/pc/peer_connection_encodings_integrationtest.cc index ae238671c2..4a93e915df 100644 --- a/third_party/libwebrtc/pc/peer_connection_encodings_integrationtest.cc +++ b/third_party/libwebrtc/pc/peer_connection_encodings_integrationtest.cc @@ -74,19 +74,10 @@ struct StringParamToString { } }; -// RTX, RED and FEC are reliability mechanisms used in combinations with other -// codecs, but are not themselves a specific codec. Typically you don't want to -// filter these out of the list of codec preferences. -bool IsReliabilityMechanism(const RtpCodecCapability& codec) { - return absl::EqualsIgnoreCase(codec.name, cricket::kRtxCodecName) || - absl::EqualsIgnoreCase(codec.name, cricket::kRedCodecName) || - absl::EqualsIgnoreCase(codec.name, cricket::kUlpfecCodecName); -} - std::string GetCurrentCodecMimeType( rtc::scoped_refptr report, const RTCOutboundRtpStreamStats& outbound_rtp) { - return outbound_rtp.codec_id.is_defined() + return outbound_rtp.codec_id.has_value() ? *report->GetAs(*outbound_rtp.codec_id)->mime_type : ""; } @@ -101,7 +92,7 @@ const RTCOutboundRtpStreamStats* FindOutboundRtpByRid( const std::vector& outbound_rtps, const absl::string_view& rid) { for (const auto* outbound_rtp : outbound_rtps) { - if (outbound_rtp->rid.is_defined() && *outbound_rtp->rid == rid) { + if (outbound_rtp->rid.has_value() && *outbound_rtp->rid == rid) { return outbound_rtp; } } @@ -163,7 +154,7 @@ class PeerConnectionEncodingsIntegrationTest : public ::testing::Test { .codecs; codecs.erase(std::remove_if(codecs.begin(), codecs.end(), [&codec_name](const RtpCodecCapability& codec) { - return !IsReliabilityMechanism(codec) && + return !codec.IsResiliencyCodec() && !absl::EqualsIgnoreCase(codec.name, codec_name); }), @@ -270,7 +261,7 @@ class PeerConnectionEncodingsIntegrationTest : public ::testing::Test { } size_t num_sending_layers = 0; for (const auto* outbound_rtp : outbound_rtps) { - if (outbound_rtp->bytes_sent.is_defined() && + if (outbound_rtp->bytes_sent.has_value() && *outbound_rtp->bytes_sent > 0u) { ++num_sending_layers; } @@ -287,11 +278,11 @@ class PeerConnectionEncodingsIntegrationTest : public ::testing::Test { std::vector outbound_rtps = report->GetStatsOfType(); auto* outbound_rtp = FindOutboundRtpByRid(outbound_rtps, rid); - if (!outbound_rtp || !outbound_rtp->scalability_mode.is_defined() || + if (!outbound_rtp || !outbound_rtp->scalability_mode.has_value() || *outbound_rtp->scalability_mode != expected_scalability_mode) { return false; } - if (outbound_rtp->frame_height.is_defined()) { + if (outbound_rtp->frame_height.has_value()) { RTC_LOG(LS_INFO) << "Waiting for target resolution (" << frame_height << "p). Currently at " << *outbound_rtp->frame_height << "p..."; @@ -299,7 +290,7 @@ class PeerConnectionEncodingsIntegrationTest : public ::testing::Test { RTC_LOG(LS_INFO) << "Waiting for target resolution. No frames encoded yet..."; } - if (!outbound_rtp->frame_height.is_defined() || + if (!outbound_rtp->frame_height.has_value() || *outbound_rtp->frame_height != frame_height) { // Sleep to avoid log spam when this is used in ASSERT_TRUE_WAIT(). rtc::Thread::Current()->SleepMs(1000); @@ -321,8 +312,8 @@ class PeerConnectionEncodingsIntegrationTest : public ::testing::Test { } else if (outbound_rtps.size() == 1u) { outbound_rtp = outbound_rtps[0]; } - if (!outbound_rtp || !outbound_rtp->frame_width.is_defined() || - !outbound_rtp->frame_height.is_defined()) { + if (!outbound_rtp || !outbound_rtp->frame_width.has_value() || + !outbound_rtp->frame_height.has_value()) { // RTP not found by rid or has not encoded a frame yet. RTC_LOG(LS_ERROR) << "rid=" << resolution.rid << " does not have " << "resolution metrics"; @@ -1200,7 +1191,7 @@ TEST_F(PeerConnectionEncodingsIntegrationTest, ASSERT_EQ(outbound_rtps.size(), 1u); std::string codec_name = GetCurrentCodecMimeType(report, *outbound_rtps[0]); EXPECT_STRCASEEQ(("video/" + vp9->name).c_str(), codec_name.c_str()); - EXPECT_EQ(outbound_rtps[0]->scalability_mode.ValueOrDefault(""), "L3T3"); + EXPECT_EQ(outbound_rtps[0]->scalability_mode.value_or(""), "L3T3"); } TEST_F(PeerConnectionEncodingsIntegrationTest, diff --git a/third_party/libwebrtc/pc/peer_connection_end_to_end_unittest.cc b/third_party/libwebrtc/pc/peer_connection_end_to_end_unittest.cc index a21d455ec5..5881cf45b5 100644 --- a/third_party/libwebrtc/pc/peer_connection_end_to_end_unittest.cc +++ b/third_party/libwebrtc/pc/peer_connection_end_to_end_unittest.cc @@ -319,8 +319,7 @@ struct AudioEncoderUnicornSparklesRainbow { using Config = webrtc::AudioEncoderL16::Config; static absl::optional SdpToConfig(webrtc::SdpAudioFormat format) { if (absl::EqualsIgnoreCase(format.name, "UnicornSparklesRainbow")) { - const webrtc::SdpAudioFormat::Parameters expected_params = { - {"num_horns", "1"}}; + const webrtc::CodecParameterMap expected_params = {{"num_horns", "1"}}; EXPECT_EQ(expected_params, format.parameters); format.parameters.clear(); format.name = "L16"; @@ -356,8 +355,7 @@ struct AudioDecoderUnicornSparklesRainbow { using Config = webrtc::AudioDecoderL16::Config; static absl::optional SdpToConfig(webrtc::SdpAudioFormat format) { if (absl::EqualsIgnoreCase(format.name, "UnicornSparklesRainbow")) { - const webrtc::SdpAudioFormat::Parameters expected_params = { - {"num_horns", "1"}}; + const webrtc::CodecParameterMap expected_params = {{"num_horns", "1"}}; EXPECT_EQ(expected_params, format.parameters); format.parameters.clear(); format.name = "L16"; diff --git a/third_party/libwebrtc/pc/peer_connection_factory.cc b/third_party/libwebrtc/pc/peer_connection_factory.cc index 8ce44d374f..6bf0ef944a 100644 --- a/third_party/libwebrtc/pc/peer_connection_factory.cc +++ b/third_party/libwebrtc/pc/peer_connection_factory.cc @@ -103,7 +103,8 @@ PeerConnectionFactory::PeerConnectionFactory( (dependencies->transport_controller_send_factory) ? std::move(dependencies->transport_controller_send_factory) : std::make_unique()), - metronome_(std::move(dependencies->metronome)) {} + decode_metronome_(std::move(dependencies->decode_metronome)), + encode_metronome_(std::move(dependencies->encode_metronome)) {} PeerConnectionFactory::PeerConnectionFactory( PeerConnectionFactoryDependencies dependencies) @@ -118,7 +119,8 @@ PeerConnectionFactory::~PeerConnectionFactory() { RTC_DCHECK_RUN_ON(signaling_thread()); worker_thread()->BlockingCall([this] { RTC_DCHECK_RUN_ON(worker_thread()); - metronome_ = nullptr; + decode_metronome_ = nullptr; + encode_metronome_ = nullptr; }); } @@ -343,7 +345,9 @@ std::unique_ptr PeerConnectionFactory::CreateCall_w( call_config.rtp_transport_controller_send_factory = transport_controller_send_factory_.get(); - call_config.metronome = metronome_.get(); + call_config.decode_metronome = decode_metronome_.get(); + call_config.encode_metronome = encode_metronome_.get(); + call_config.pacer_burst_interval = configuration.pacer_burst_interval; return context_->call_factory()->CreateCall(call_config); } diff --git a/third_party/libwebrtc/pc/peer_connection_factory.h b/third_party/libwebrtc/pc/peer_connection_factory.h index c3760c02c9..a8af9f5efa 100644 --- a/third_party/libwebrtc/pc/peer_connection_factory.h +++ b/third_party/libwebrtc/pc/peer_connection_factory.h @@ -109,7 +109,7 @@ class PeerConnectionFactory : public PeerConnectionFactoryInterface { } const FieldTrialsView& field_trials() const { - return context_->field_trials(); + return context_->env().field_trials(); } cricket::MediaEngineInterface* media_engine() const; @@ -147,7 +147,8 @@ class PeerConnectionFactory : public PeerConnectionFactoryInterface { std::unique_ptr neteq_factory_; const std::unique_ptr transport_controller_send_factory_; - std::unique_ptr metronome_ RTC_GUARDED_BY(worker_thread()); + std::unique_ptr decode_metronome_ RTC_GUARDED_BY(worker_thread()); + std::unique_ptr encode_metronome_ RTC_GUARDED_BY(worker_thread()); }; } // namespace webrtc diff --git a/third_party/libwebrtc/pc/peer_connection_field_trial_tests.cc b/third_party/libwebrtc/pc/peer_connection_field_trial_tests.cc index 4cbe24986c..ae566359e4 100644 --- a/third_party/libwebrtc/pc/peer_connection_field_trial_tests.cc +++ b/third_party/libwebrtc/pc/peer_connection_field_trial_tests.cc @@ -264,7 +264,7 @@ TEST_F(PeerConnectionFieldTrialTest, ApplyFakeNetworkConfig) { std::vector outbound_rtp_stats = caller->GetStats()->GetStatsOfType(); ASSERT_GE(outbound_rtp_stats.size(), 1u); - ASSERT_TRUE(outbound_rtp_stats[0]->target_bitrate.is_defined()); + ASSERT_TRUE(outbound_rtp_stats[0]->target_bitrate.has_value()); // Link capacity is limited to 500k, so BWE is expected to be close to 500k. ASSERT_LE(*outbound_rtp_stats[0]->target_bitrate, 500'000 * 1.1); } diff --git a/third_party/libwebrtc/pc/peer_connection_header_extension_unittest.cc b/third_party/libwebrtc/pc/peer_connection_header_extension_unittest.cc index 277979b330..15b1ae6d1c 100644 --- a/third_party/libwebrtc/pc/peer_connection_header_extension_unittest.cc +++ b/third_party/libwebrtc/pc/peer_connection_header_extension_unittest.cc @@ -90,8 +90,7 @@ class PeerConnectionHeaderExtensionTest EnableFakeMedia(factory_dependencies, std::move(media_engine)); factory_dependencies.event_log_factory = - std::make_unique( - factory_dependencies.task_queue_factory.get()); + std::make_unique(); auto pc_factory = CreateModularPeerConnectionFactory(std::move(factory_dependencies)); diff --git a/third_party/libwebrtc/pc/peer_connection_histogram_unittest.cc b/third_party/libwebrtc/pc/peer_connection_histogram_unittest.cc index 58bd6ebb48..365f58a806 100644 --- a/third_party/libwebrtc/pc/peer_connection_histogram_unittest.cc +++ b/third_party/libwebrtc/pc/peer_connection_histogram_unittest.cc @@ -15,7 +15,6 @@ #include #include "absl/types/optional.h" -#include "api/call/call_factory_interface.h" #include "api/jsep.h" #include "api/jsep_session_description.h" #include "api/peer_connection_interface.h" diff --git a/third_party/libwebrtc/pc/peer_connection_integrationtest.cc b/third_party/libwebrtc/pc/peer_connection_integrationtest.cc index bfff86ee93..c960a36b5e 100644 --- a/third_party/libwebrtc/pc/peer_connection_integrationtest.cc +++ b/third_party/libwebrtc/pc/peer_connection_integrationtest.cc @@ -1356,15 +1356,15 @@ TEST_P(PeerConnectionIntegrationTest, NewGetStatsManyAudioAndManyVideoStreams) { ASSERT_EQ(outbound_stream_stats.size(), 4u); std::vector outbound_track_ids; for (const auto& stat : outbound_stream_stats) { - ASSERT_TRUE(stat->bytes_sent.is_defined()); + ASSERT_TRUE(stat->bytes_sent.has_value()); EXPECT_LT(0u, *stat->bytes_sent); if (*stat->kind == "video") { - ASSERT_TRUE(stat->key_frames_encoded.is_defined()); + ASSERT_TRUE(stat->key_frames_encoded.has_value()); EXPECT_GT(*stat->key_frames_encoded, 0u); - ASSERT_TRUE(stat->frames_encoded.is_defined()); + ASSERT_TRUE(stat->frames_encoded.has_value()); EXPECT_GE(*stat->frames_encoded, *stat->key_frames_encoded); } - ASSERT_TRUE(stat->media_source_id.is_defined()); + ASSERT_TRUE(stat->media_source_id.has_value()); const RTCMediaSourceStats* media_source = static_cast( caller_report->Get(*stat->media_source_id)); @@ -1381,12 +1381,12 @@ TEST_P(PeerConnectionIntegrationTest, NewGetStatsManyAudioAndManyVideoStreams) { ASSERT_EQ(4u, inbound_stream_stats.size()); std::vector inbound_track_ids; for (const auto& stat : inbound_stream_stats) { - ASSERT_TRUE(stat->bytes_received.is_defined()); + ASSERT_TRUE(stat->bytes_received.has_value()); EXPECT_LT(0u, *stat->bytes_received); if (*stat->kind == "video") { - ASSERT_TRUE(stat->key_frames_decoded.is_defined()); + ASSERT_TRUE(stat->key_frames_decoded.has_value()); EXPECT_GT(*stat->key_frames_decoded, 0u); - ASSERT_TRUE(stat->frames_decoded.is_defined()); + ASSERT_TRUE(stat->frames_decoded.has_value()); EXPECT_GE(*stat->frames_decoded, *stat->key_frames_decoded); } inbound_track_ids.push_back(*stat->track_identifier); @@ -1417,7 +1417,7 @@ TEST_P(PeerConnectionIntegrationTest, auto inbound_stream_stats = report->GetStatsOfType(); ASSERT_EQ(1U, inbound_stream_stats.size()); - ASSERT_TRUE(inbound_stream_stats[0]->bytes_received.is_defined()); + ASSERT_TRUE(inbound_stream_stats[0]->bytes_received.has_value()); ASSERT_GT(*inbound_stream_stats[0]->bytes_received, 0U); } @@ -1464,7 +1464,7 @@ TEST_P(PeerConnectionIntegrationTest, auto inbound_rtps = report->GetStatsOfType(); auto index = FindFirstMediaStatsIndexByKind("audio", inbound_rtps); ASSERT_GE(index, 0); - EXPECT_TRUE(inbound_rtps[index]->audio_level.is_defined()); + EXPECT_TRUE(inbound_rtps[index]->audio_level.has_value()); } // Test that DTLS 1.0 is used if both sides only support DTLS 1.0. @@ -2952,7 +2952,7 @@ double GetAudioEnergyStat(PeerConnectionIntegrationWrapper* pc) { auto inbound_rtps = report->GetStatsOfType(); RTC_CHECK(!inbound_rtps.empty()); auto* inbound_rtp = inbound_rtps[0]; - if (!inbound_rtp->total_audio_energy.is_defined()) { + if (!inbound_rtp->total_audio_energy.has_value()) { return 0.0; } return *inbound_rtp->total_audio_energy; @@ -3776,7 +3776,7 @@ int NacksReceivedCount(PeerConnectionIntegrationWrapper& pc) { ADD_FAILURE(); return 0; } - if (!sender_stats[0]->nack_count.is_defined()) { + if (!sender_stats[0]->nack_count.has_value()) { return 0; } return *sender_stats[0]->nack_count; @@ -3789,7 +3789,7 @@ int NacksSentCount(PeerConnectionIntegrationWrapper& pc) { ADD_FAILURE(); return 0; } - if (!receiver_stats[0]->nack_count.is_defined()) { + if (!receiver_stats[0]->nack_count.has_value()) { return 0; } return *receiver_stats[0]->nack_count; diff --git a/third_party/libwebrtc/pc/peer_connection_interface_unittest.cc b/third_party/libwebrtc/pc/peer_connection_interface_unittest.cc index 5ee9881b84..61794bb0f9 100644 --- a/third_party/libwebrtc/pc/peer_connection_interface_unittest.cc +++ b/third_party/libwebrtc/pc/peer_connection_interface_unittest.cc @@ -641,8 +641,7 @@ class PeerConnectionFactoryForTest : public PeerConnectionFactory { // level, and using a real one could make tests flaky when run in parallel. dependencies.adm = FakeAudioCaptureModule::Create(); EnableMediaWithDefaults(dependencies); - dependencies.event_log_factory = std::make_unique( - dependencies.task_queue_factory.get()); + dependencies.event_log_factory = std::make_unique(); return rtc::make_ref_counted( std::move(dependencies)); @@ -2815,7 +2814,7 @@ TEST_F(PeerConnectionInterfaceTestPlanB, // This tests that a default MediaStream is not created if a remote session // description is updated to not have any MediaStreams. // Don't run under Unified Plan since this behavior is Plan B specific. -TEST_F(PeerConnectionInterfaceTestPlanB, VerifyDefaultStreamIsNotCreated) { +TEST_F(PeerConnectionInterfaceTestPlanB, VerifyDefaultStreamIsNotRecreated) { RTCConfiguration config; CreatePeerConnection(config); CreateAndSetRemoteOffer(GetSdpStringWithStream1()); @@ -2823,7 +2822,7 @@ TEST_F(PeerConnectionInterfaceTestPlanB, VerifyDefaultStreamIsNotCreated) { EXPECT_TRUE( CompareStreamCollections(observer_.remote_streams(), reference.get())); - CreateAndSetRemoteOffer(kSdpStringWithoutStreams); + CreateAndSetRemoteOffer(kSdpStringWithMsidWithoutStreams); EXPECT_EQ(0u, observer_.remote_streams()->count()); } diff --git a/third_party/libwebrtc/pc/peer_connection_media_unittest.cc b/third_party/libwebrtc/pc/peer_connection_media_unittest.cc index 387094cc4f..b892eacb78 100644 --- a/third_party/libwebrtc/pc/peer_connection_media_unittest.cc +++ b/third_party/libwebrtc/pc/peer_connection_media_unittest.cc @@ -66,7 +66,6 @@ #ifdef WEBRTC_ANDROID #include "pc/test/android_test_initializer.h" #endif -#include "rtc_base/gunit.h" #include "rtc_base/virtual_socket_server.h" #include "test/gmock.h" @@ -78,6 +77,7 @@ using RTCOfferAnswerOptions = PeerConnectionInterface::RTCOfferAnswerOptions; using ::testing::Bool; using ::testing::Combine; using ::testing::ElementsAre; +using ::testing::HasSubstr; using ::testing::NotNull; using ::testing::Values; @@ -175,8 +175,7 @@ class PeerConnectionMediaBaseTest : public ::testing::Test { factory_dependencies.task_queue_factory = CreateDefaultTaskQueueFactory(); EnableFakeMedia(factory_dependencies, std::move(media_engine)); factory_dependencies.event_log_factory = - std::make_unique( - factory_dependencies.task_queue_factory.get()); + std::make_unique(); auto pc_factory = CreateModularPeerConnectionFactory(std::move(factory_dependencies)); @@ -287,8 +286,8 @@ TEST_P(PeerConnectionMediaTest, std::string error; ASSERT_FALSE(callee->SetRemoteDescription(caller->CreateOffer(), &error)); - EXPECT_PRED_FORMAT2(AssertStartsWith, error, - "Failed to set remote offer sdp: Failed to create"); + EXPECT_THAT(error, + HasSubstr("Failed to set remote offer sdp: Failed to create")); } TEST_P(PeerConnectionMediaTest, @@ -298,8 +297,8 @@ TEST_P(PeerConnectionMediaTest, std::string error; ASSERT_FALSE(caller->SetLocalDescription(caller->CreateOffer(), &error)); - EXPECT_PRED_FORMAT2(AssertStartsWith, error, - "Failed to set local offer sdp: Failed to create"); + EXPECT_THAT(error, + HasSubstr("Failed to set local offer sdp: Failed to create")); } std::vector GetIds( diff --git a/third_party/libwebrtc/pc/peer_connection_rampup_tests.cc b/third_party/libwebrtc/pc/peer_connection_rampup_tests.cc index 0fd3c27f7d..cc645a0ea7 100644 --- a/third_party/libwebrtc/pc/peer_connection_rampup_tests.cc +++ b/third_party/libwebrtc/pc/peer_connection_rampup_tests.cc @@ -309,15 +309,17 @@ class PeerConnectionRampUpTest : public ::testing::Test { auto stats = caller_->GetStats(); auto transport_stats = stats->GetStatsOfType(); if (transport_stats.size() == 0u || - !transport_stats[0]->selected_candidate_pair_id.is_defined()) { + !transport_stats[0]->selected_candidate_pair_id.has_value()) { return 0; } std::string selected_ice_id = - transport_stats[0]->selected_candidate_pair_id.ValueToString(); + transport_stats[0] + ->GetAttribute(transport_stats[0]->selected_candidate_pair_id) + .ToString(); // Use the selected ICE candidate pair ID to get the appropriate ICE stats. const RTCIceCandidatePairStats ice_candidate_pair_stats = stats->Get(selected_ice_id)->cast_to(); - if (ice_candidate_pair_stats.available_outgoing_bitrate.is_defined()) { + if (ice_candidate_pair_stats.available_outgoing_bitrate.has_value()) { return *ice_candidate_pair_stats.available_outgoing_bitrate; } // We couldn't get the `available_outgoing_bitrate` for the active candidate diff --git a/third_party/libwebrtc/pc/peer_connection_rtp_unittest.cc b/third_party/libwebrtc/pc/peer_connection_rtp_unittest.cc index 1a97a4bb44..77c8cecbb2 100644 --- a/third_party/libwebrtc/pc/peer_connection_rtp_unittest.cc +++ b/third_party/libwebrtc/pc/peer_connection_rtp_unittest.cc @@ -1836,14 +1836,16 @@ TEST_F(PeerConnectionMsidSignalingTest, UnifiedPlanTalkingToOurself) { // Offer should have had both a=msid and a=ssrc MSID lines. auto* offer = callee->pc()->remote_description(); - EXPECT_EQ((cricket::kMsidSignalingMediaSection | - cricket::kMsidSignalingSsrcAttribute), - offer->description()->msid_signaling()); + EXPECT_EQ( + (cricket::kMsidSignalingSemantic | cricket::kMsidSignalingMediaSection | + cricket::kMsidSignalingSsrcAttribute), + offer->description()->msid_signaling()); // Answer should have had only a=msid lines. auto* answer = caller->pc()->remote_description(); - EXPECT_EQ(cricket::kMsidSignalingMediaSection, - answer->description()->msid_signaling()); + EXPECT_EQ( + cricket::kMsidSignalingSemantic | cricket::kMsidSignalingMediaSection, + answer->description()->msid_signaling()); } TEST_F(PeerConnectionMsidSignalingTest, PlanBOfferToUnifiedPlanAnswer) { @@ -1856,13 +1858,15 @@ TEST_F(PeerConnectionMsidSignalingTest, PlanBOfferToUnifiedPlanAnswer) { // Offer should have only a=ssrc MSID lines. auto* offer = callee->pc()->remote_description(); - EXPECT_EQ(cricket::kMsidSignalingSsrcAttribute, - offer->description()->msid_signaling()); + EXPECT_EQ( + cricket::kMsidSignalingSemantic | cricket::kMsidSignalingSsrcAttribute, + offer->description()->msid_signaling()); // Answer should have only a=ssrc MSID lines to match the offer. auto* answer = caller->pc()->remote_description(); - EXPECT_EQ(cricket::kMsidSignalingSsrcAttribute, - answer->description()->msid_signaling()); + EXPECT_EQ( + cricket::kMsidSignalingSemantic | cricket::kMsidSignalingSsrcAttribute, + answer->description()->msid_signaling()); } // This tests that a Plan B endpoint appropriately sets the remote description @@ -1884,9 +1888,10 @@ TEST_F(PeerConnectionMsidSignalingTest, UnifiedPlanToPlanBAnswer) { // Offer should have had both a=msid and a=ssrc MSID lines. auto* offer = callee->pc()->remote_description(); - EXPECT_EQ((cricket::kMsidSignalingMediaSection | - cricket::kMsidSignalingSsrcAttribute), - offer->description()->msid_signaling()); + EXPECT_EQ( + (cricket::kMsidSignalingSemantic | cricket::kMsidSignalingMediaSection | + cricket::kMsidSignalingSsrcAttribute), + offer->description()->msid_signaling()); // Callee should always have 1 stream for all of it's receivers. const auto& track_events = callee->observer()->add_track_events_; @@ -1907,7 +1912,8 @@ TEST_F(PeerConnectionMsidSignalingTest, PureUnifiedPlanToUs) { auto offer = caller->CreateOffer(); // Simulate a pure Unified Plan offerer by setting the MSID signaling to media // section only. - offer->description()->set_msid_signaling(cricket::kMsidSignalingMediaSection); + offer->description()->set_msid_signaling(cricket::kMsidSignalingSemantic | + cricket::kMsidSignalingMediaSection); ASSERT_TRUE( caller->SetLocalDescription(CloneSessionDescription(offer.get()))); @@ -1915,8 +1921,9 @@ TEST_F(PeerConnectionMsidSignalingTest, PureUnifiedPlanToUs) { // Answer should have only a=msid to match the offer. auto answer = callee->CreateAnswer(); - EXPECT_EQ(cricket::kMsidSignalingMediaSection, - answer->description()->msid_signaling()); + EXPECT_EQ( + cricket::kMsidSignalingSemantic | cricket::kMsidSignalingMediaSection, + answer->description()->msid_signaling()); } // Sender setups in a call. diff --git a/third_party/libwebrtc/pc/peer_connection_signaling_unittest.cc b/third_party/libwebrtc/pc/peer_connection_signaling_unittest.cc index 190fb38b43..7764be923d 100644 --- a/third_party/libwebrtc/pc/peer_connection_signaling_unittest.cc +++ b/third_party/libwebrtc/pc/peer_connection_signaling_unittest.cc @@ -64,6 +64,7 @@ #include "rtc_base/rtc_certificate_generator.h" #include "rtc_base/string_encode.h" #include "rtc_base/thread.h" +#include "test/gmock.h" #include "test/gtest.h" #ifdef WEBRTC_ANDROID #include "pc/test/android_test_initializer.h" @@ -80,6 +81,7 @@ using RTCConfiguration = PeerConnectionInterface::RTCConfiguration; using RTCOfferAnswerOptions = PeerConnectionInterface::RTCOfferAnswerOptions; using ::testing::Bool; using ::testing::Combine; +using ::testing::StartsWith; using ::testing::Values; namespace { @@ -343,8 +345,7 @@ TEST_P(PeerConnectionSignalingStateTest, CreateOffer) { } else { std::string error; ASSERT_FALSE(wrapper->CreateOffer(RTCOfferAnswerOptions(), &error)); - EXPECT_PRED_FORMAT2(AssertStartsWith, error, - "CreateOffer called when PeerConnection is closed."); + EXPECT_EQ(error, "CreateOffer called when PeerConnection is closed."); } } @@ -379,9 +380,9 @@ TEST_P(PeerConnectionSignalingStateTest, SetLocalOffer) { std::string error; ASSERT_FALSE(wrapper->SetLocalDescription(std::move(offer), &error)); - EXPECT_PRED_FORMAT2( - AssertStartsWith, error, - "Failed to set local offer sdp: Called in wrong state:"); + EXPECT_THAT( + error, + StartsWith("Failed to set local offer sdp: Called in wrong state:")); } } @@ -398,9 +399,9 @@ TEST_P(PeerConnectionSignalingStateTest, SetLocalPrAnswer) { } else { std::string error; ASSERT_FALSE(wrapper->SetLocalDescription(std::move(pranswer), &error)); - EXPECT_PRED_FORMAT2( - AssertStartsWith, error, - "Failed to set local pranswer sdp: Called in wrong state:"); + EXPECT_THAT( + error, + StartsWith("Failed to set local pranswer sdp: Called in wrong state:")); } } @@ -416,9 +417,9 @@ TEST_P(PeerConnectionSignalingStateTest, SetLocalAnswer) { } else { std::string error; ASSERT_FALSE(wrapper->SetLocalDescription(std::move(answer), &error)); - EXPECT_PRED_FORMAT2( - AssertStartsWith, error, - "Failed to set local answer sdp: Called in wrong state:"); + EXPECT_THAT( + error, + StartsWith("Failed to set local answer sdp: Called in wrong state:")); } } @@ -435,9 +436,9 @@ TEST_P(PeerConnectionSignalingStateTest, SetRemoteOffer) { } else { std::string error; ASSERT_FALSE(wrapper->SetRemoteDescription(std::move(offer), &error)); - EXPECT_PRED_FORMAT2( - AssertStartsWith, error, - "Failed to set remote offer sdp: Called in wrong state:"); + EXPECT_THAT( + error, + StartsWith("Failed to set remote offer sdp: Called in wrong state:")); } } @@ -454,9 +455,10 @@ TEST_P(PeerConnectionSignalingStateTest, SetRemotePrAnswer) { } else { std::string error; ASSERT_FALSE(wrapper->SetRemoteDescription(std::move(pranswer), &error)); - EXPECT_PRED_FORMAT2( - AssertStartsWith, error, - "Failed to set remote pranswer sdp: Called in wrong state:"); + EXPECT_THAT( + error, + StartsWith( + "Failed to set remote pranswer sdp: Called in wrong state:")); } } @@ -472,9 +474,9 @@ TEST_P(PeerConnectionSignalingStateTest, SetRemoteAnswer) { } else { std::string error; ASSERT_FALSE(wrapper->SetRemoteDescription(std::move(answer), &error)); - EXPECT_PRED_FORMAT2( - AssertStartsWith, error, - "Failed to set remote answer sdp: Called in wrong state:"); + EXPECT_THAT( + error, + StartsWith("Failed to set remote answer sdp: Called in wrong state:")); } } diff --git a/third_party/libwebrtc/pc/peer_connection_simulcast_unittest.cc b/third_party/libwebrtc/pc/peer_connection_simulcast_unittest.cc index bffb5d9e9f..06f38848e1 100644 --- a/third_party/libwebrtc/pc/peer_connection_simulcast_unittest.cc +++ b/third_party/libwebrtc/pc/peer_connection_simulcast_unittest.cc @@ -102,21 +102,6 @@ std::ostream& operator<<( // no-presubmit-check TODO(webrtc:8982) } // namespace cricket -namespace { - -#if RTC_METRICS_ENABLED -std::vector CreateLayers(int num_layers, bool active) { - rtc::UniqueStringGenerator rid_generator; - std::vector rids; - for (int i = 0; i < num_layers; ++i) { - rids.push_back(rid_generator.GenerateString()); - } - return webrtc::CreateLayers(rids, active); -} -#endif - -} // namespace - namespace webrtc { class PeerConnectionSimulcastTests : public ::testing::Test { @@ -214,16 +199,6 @@ class PeerConnectionSimulcastTests : public ::testing::Test { rtc::scoped_refptr pc_factory_; }; -#if RTC_METRICS_ENABLED -// This class is used to test the metrics emitted for simulcast. -class PeerConnectionSimulcastMetricsTests - : public PeerConnectionSimulcastTests, - public ::testing::WithParamInterface { - protected: - PeerConnectionSimulcastMetricsTests() { metrics::Reset(); } -}; -#endif - // Validates that RIDs are supported arguments when adding a transceiver. TEST_F(PeerConnectionSimulcastTests, CanCreateTransceiverWithRid) { auto pc = CreatePeerConnectionWrapper(); @@ -603,27 +578,4 @@ TEST_F(PeerConnectionSimulcastTests, SimulcastSldModificationRejected) { EXPECT_TRUE(modified_offer); EXPECT_TRUE(local->SetLocalDescription(std::move(modified_offer))); } - -#if RTC_METRICS_ENABLED - -const int kMaxLayersInMetricsTest = 8; - -// Checks that the number of send encodings is logged in a metric. -TEST_P(PeerConnectionSimulcastMetricsTests, NumberOfSendEncodingsIsLogged) { - auto local = CreatePeerConnectionWrapper(); - auto num_layers = GetParam(); - auto layers = ::CreateLayers(num_layers, true); - AddTransceiver(local.get(), layers); - EXPECT_EQ(1, metrics::NumSamples( - "WebRTC.PeerConnection.Simulcast.NumberOfSendEncodings")); - EXPECT_EQ(1, metrics::NumEvents( - "WebRTC.PeerConnection.Simulcast.NumberOfSendEncodings", - num_layers)); -} - -INSTANTIATE_TEST_SUITE_P(NumberOfSendEncodings, - PeerConnectionSimulcastMetricsTests, - ::testing::Range(0, kMaxLayersInMetricsTest)); -#endif - } // namespace webrtc diff --git a/third_party/libwebrtc/pc/rtc_stats_collector.cc b/third_party/libwebrtc/pc/rtc_stats_collector.cc index 2bac176aac..a5a3067fa1 100644 --- a/third_party/libwebrtc/pc/rtc_stats_collector.cc +++ b/third_party/libwebrtc/pc/rtc_stats_collector.cc @@ -164,14 +164,14 @@ std::string RTCMediaSourceStatsIDFromKindAndAttachment( return sb.str(); } -const char* CandidateTypeToRTCIceCandidateType(const std::string& type) { - if (type == cricket::LOCAL_PORT_TYPE) +const char* CandidateTypeToRTCIceCandidateType(const cricket::Candidate& c) { + if (c.is_local()) return "host"; - if (type == cricket::STUN_PORT_TYPE) + if (c.is_stun()) return "srflx"; - if (type == cricket::PRFLX_PORT_TYPE) + if (c.is_prflx()) return "prflx"; - if (type == cricket::RELAY_PORT_TYPE) + if (c.is_relay()) return "relay"; RTC_DCHECK_NOTREACHED(); return nullptr; @@ -551,7 +551,7 @@ CreateRemoteOutboundAudioStreamStats( stats->ssrc = voice_receiver_info.ssrc(); stats->kind = "audio"; stats->transport_id = transport_id; - if (inbound_audio_stats.codec_id.is_defined()) { + if (inbound_audio_stats.codec_id.has_value()) { stats->codec_id = *inbound_audio_stats.codec_id; } // - RTCSentRtpStreamStats. @@ -890,7 +890,7 @@ ProduceRemoteInboundRtpStreamStatsFromReportBlockData( // transport paired with the RTP transport, otherwise the same // transport is used for RTCP and RTP. remote_inbound->transport_id = - transport.rtcp_transport_stats_id.is_defined() + transport.rtcp_transport_stats_id.has_value() ? *transport.rtcp_transport_stats_id : *outbound_rtp.transport_id; } @@ -898,13 +898,13 @@ ProduceRemoteInboundRtpStreamStatsFromReportBlockData( // codec is switched out on the fly we may have received a Report Block // based on the previous codec and there is no way to tell which point in // time the codec changed for the remote end. - const auto* codec_from_id = outbound_rtp.codec_id.is_defined() + const auto* codec_from_id = outbound_rtp.codec_id.has_value() ? report.Get(*outbound_rtp.codec_id) : nullptr; if (codec_from_id) { remote_inbound->codec_id = *outbound_rtp.codec_id; const auto& codec = codec_from_id->cast_to(); - if (codec.clock_rate.is_defined()) { + if (codec.clock_rate.has_value()) { remote_inbound->jitter = report_block.jitter(*codec.clock_rate).seconds(); } @@ -1001,7 +1001,7 @@ const std::string& ProduceIceCandidateStats(Timestamp timestamp, candidate_stats->port = static_cast(candidate.address().port()); candidate_stats->protocol = candidate.protocol(); candidate_stats->candidate_type = - CandidateTypeToRTCIceCandidateType(candidate.type()); + CandidateTypeToRTCIceCandidateType(candidate); candidate_stats->priority = static_cast(candidate.priority()); candidate_stats->foundation = candidate.foundation(); auto related_address = candidate.related_address(); @@ -1051,7 +1051,7 @@ RTCStatsCollector::CreateReportFilteredBySelector( auto encodings = sender_selector->GetParametersInternal().encodings; for (const auto* outbound_rtp : report->GetStatsOfType()) { - RTC_DCHECK(outbound_rtp->ssrc.is_defined()); + RTC_DCHECK(outbound_rtp->ssrc.has_value()); auto it = std::find_if(encodings.begin(), encodings.end(), [ssrc = *outbound_rtp->ssrc]( const RtpEncodingParameters& encoding) { @@ -1071,7 +1071,7 @@ RTCStatsCollector::CreateReportFilteredBySelector( if (ssrc.has_value()) { for (const auto* inbound_rtp : report->GetStatsOfType()) { - RTC_DCHECK(inbound_rtp->ssrc.is_defined()); + RTC_DCHECK(inbound_rtp->ssrc.has_value()); if (*inbound_rtp->ssrc == *ssrc) { rtpstream_ids.push_back(inbound_rtp->id()); } @@ -2124,7 +2124,9 @@ void RTCStatsCollector::PrepareTransceiverStatsInfosAndCallStats_s_w_n() { } } - // Create the TrackMediaInfoMap for each transceiver stats object. + // Create the TrackMediaInfoMap for each transceiver stats object + // and keep track of whether we have at least one audio receiver. + bool has_audio_receiver = false; for (auto& stats : transceiver_stats_infos_) { auto transceiver = stats.transceiver; absl::optional voice_media_info; @@ -2159,10 +2161,14 @@ void RTCStatsCollector::PrepareTransceiverStatsInfosAndCallStats_s_w_n() { stats.track_media_info_map.Initialize(std::move(voice_media_info), std::move(video_media_info), senders, receivers); + if (transceiver->media_type() == cricket::MEDIA_TYPE_AUDIO) { + has_audio_receiver |= !receivers.empty(); + } } call_stats_ = pc_->GetCallStats(); - audio_device_stats_ = pc_->GetAudioDeviceStats(); + audio_device_stats_ = + has_audio_receiver ? pc_->GetAudioDeviceStats() : absl::nullopt; }); for (auto& stats : transceiver_stats_infos_) { @@ -2188,14 +2194,4 @@ void RTCStatsCollector::OnSctpDataChannelStateChanged( } } -const char* CandidateTypeToRTCIceCandidateTypeForTesting( - const std::string& type) { - return CandidateTypeToRTCIceCandidateType(type); -} - -const char* DataStateToRTCDataChannelStateForTesting( - DataChannelInterface::DataState state) { - return DataStateToRTCDataChannelState(state); -} - } // namespace webrtc diff --git a/third_party/libwebrtc/pc/rtc_stats_collector.h b/third_party/libwebrtc/pc/rtc_stats_collector.h index 4c68e77086..505979c5ea 100644 --- a/third_party/libwebrtc/pc/rtc_stats_collector.h +++ b/third_party/libwebrtc/pc/rtc_stats_collector.h @@ -322,11 +322,6 @@ class RTCStatsCollector : public rtc::RefCountInterface { InternalRecord internal_record_; }; -const char* CandidateTypeToRTCIceCandidateTypeForTesting( - const std::string& type); -const char* DataStateToRTCDataChannelStateForTesting( - DataChannelInterface::DataState state); - } // namespace webrtc #endif // PC_RTC_STATS_COLLECTOR_H_ diff --git a/third_party/libwebrtc/pc/rtc_stats_collector_unittest.cc b/third_party/libwebrtc/pc/rtc_stats_collector_unittest.cc index 055be6fe99..61b3bca1db 100644 --- a/third_party/libwebrtc/pc/rtc_stats_collector_unittest.cc +++ b/third_party/libwebrtc/pc/rtc_stats_collector_unittest.cc @@ -29,6 +29,7 @@ #include "api/media_stream_track.h" #include "api/rtp_parameters.h" #include "api/rtp_transceiver_direction.h" +#include "api/stats/attribute.h" #include "api/stats/rtc_stats.h" #include "api/stats/rtc_stats_report.h" #include "api/stats/rtcstats_objects.h" @@ -2303,7 +2304,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCInboundRtpStreamStats_Audio_PlayoutId) { ASSERT_TRUE(report->Get("ITTransportName1A1")); auto stats = report->Get("ITTransportName1A1")->cast_to(); - ASSERT_FALSE(stats.playout_id.is_defined()); + ASSERT_FALSE(stats.playout_id.has_value()); } { // We do expect a playout id when receiving. @@ -2314,7 +2315,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCInboundRtpStreamStats_Audio_PlayoutId) { ASSERT_TRUE(report->Get("ITTransportName1A1")); auto stats = report->Get("ITTransportName1A1")->cast_to(); - ASSERT_TRUE(stats.playout_id.is_defined()); + ASSERT_TRUE(stats.playout_id.has_value()); EXPECT_EQ(*stats.playout_id, "AP"); } } @@ -2478,6 +2479,10 @@ TEST_F(RTCStatsCollectorTest, CollectRTCAudioPlayoutStats) { audio_device_stats.total_playout_delay_s = 5; pc_->SetAudioDeviceStats(audio_device_stats); + pc_->AddVoiceChannel("AudioMid", "TransportName", {}); + stats_->SetupRemoteTrackAndReceiver( + cricket::MEDIA_TYPE_AUDIO, "RemoteAudioTrackID", "RemoteStreamId", 1); + rtc::scoped_refptr report = stats_->GetStatsReport(); auto stats_of_track_type = report->GetStatsOfType(); ASSERT_EQ(1U, stats_of_track_type.size()); @@ -2526,7 +2531,7 @@ TEST_F(RTCStatsCollectorTest, CollectGoogTimingFrameInfo) { rtc::scoped_refptr report = stats_->GetStatsReport(); auto inbound_rtps = report->GetStatsOfType(); ASSERT_EQ(inbound_rtps.size(), 1u); - ASSERT_TRUE(inbound_rtps[0]->goog_timing_frame_info.is_defined()); + ASSERT_TRUE(inbound_rtps[0]->goog_timing_frame_info.has_value()); EXPECT_EQ(*inbound_rtps[0]->goog_timing_frame_info, "1,2,3,4,5,6,7,8,9,10,11,12,13,1,0"); } @@ -3135,8 +3140,8 @@ TEST_F(RTCStatsCollectorTest, rtc::scoped_refptr report = stats_->GetStatsReport(); ASSERT_TRUE(report->Get("SV42")); auto video_stats = report->Get("SV42")->cast_to(); - EXPECT_FALSE(video_stats.frames_per_second.is_defined()); - EXPECT_FALSE(video_stats.frames.is_defined()); + EXPECT_FALSE(video_stats.frames_per_second.has_value()); + EXPECT_FALSE(video_stats.frames.has_value()); } // The track not having a source is not expected to be true in practise, but @@ -3165,8 +3170,8 @@ TEST_F(RTCStatsCollectorTest, rtc::scoped_refptr report = stats_->GetStatsReport(); ASSERT_TRUE(report->Get("SV42")); auto video_stats = report->Get("SV42")->cast_to(); - EXPECT_FALSE(video_stats.width.is_defined()); - EXPECT_FALSE(video_stats.height.is_defined()); + EXPECT_FALSE(video_stats.width.has_value()); + EXPECT_FALSE(video_stats.height.has_value()); } TEST_F(RTCStatsCollectorTest, @@ -3367,9 +3372,9 @@ TEST_P(RTCStatsCollectorTestWithParamKind, auto& remote_inbound_rtp = report->Get(remote_inbound_rtp_id) ->cast_to(); - EXPECT_TRUE(remote_inbound_rtp.round_trip_time_measurements.is_defined()); + EXPECT_TRUE(remote_inbound_rtp.round_trip_time_measurements.has_value()); EXPECT_EQ(0, *remote_inbound_rtp.round_trip_time_measurements); - EXPECT_FALSE(remote_inbound_rtp.round_trip_time.is_defined()); + EXPECT_FALSE(remote_inbound_rtp.round_trip_time.has_value()); } TEST_P(RTCStatsCollectorTestWithParamKind, @@ -3431,10 +3436,10 @@ TEST_P(RTCStatsCollectorTestWithParamKind, auto& remote_inbound_rtp = report->Get(remote_inbound_rtp_id) ->cast_to(); - EXPECT_TRUE(remote_inbound_rtp.codec_id.is_defined()); + EXPECT_TRUE(remote_inbound_rtp.codec_id.has_value()); EXPECT_TRUE(report->Get(*remote_inbound_rtp.codec_id)); - EXPECT_TRUE(remote_inbound_rtp.jitter.is_defined()); + EXPECT_TRUE(remote_inbound_rtp.jitter.has_value()); // The jitter (in seconds) is the report block's jitter divided by the codec's // clock rate. EXPECT_EQ(5.0, *remote_inbound_rtp.jitter); @@ -3471,7 +3476,7 @@ TEST_P(RTCStatsCollectorTestWithParamKind, auto& remote_inbound_rtp = report->Get(remote_inbound_rtp_id) ->cast_to(); - EXPECT_TRUE(remote_inbound_rtp.transport_id.is_defined()); + EXPECT_TRUE(remote_inbound_rtp.transport_id.has_value()); EXPECT_EQ("TTransportName2", // 2 for RTCP *remote_inbound_rtp.transport_id); EXPECT_TRUE(report->Get(*remote_inbound_rtp.transport_id)); @@ -3716,12 +3721,15 @@ class RTCTestStats : public RTCStats { WEBRTC_RTCSTATS_DECL(); RTCTestStats(const std::string& id, Timestamp timestamp) - : RTCStats(id, timestamp), dummy_stat("dummyStat") {} + : RTCStats(id, timestamp) {} RTCStatsMember dummy_stat; }; -WEBRTC_RTCSTATS_IMPL(RTCTestStats, RTCStats, "test-stats", &dummy_stat) +WEBRTC_RTCSTATS_IMPL(RTCTestStats, + RTCStats, + "test-stats", + AttributeInit("dummyStat", &dummy_stat)) // Overrides the stats collection to verify thread usage and that the resulting // partial reports are merged. diff --git a/third_party/libwebrtc/pc/rtc_stats_integrationtest.cc b/third_party/libwebrtc/pc/rtc_stats_integrationtest.cc index 648efab69a..002f9d34b5 100644 --- a/third_party/libwebrtc/pc/rtc_stats_integrationtest.cc +++ b/third_party/libwebrtc/pc/rtc_stats_integrationtest.cc @@ -206,106 +206,112 @@ class RTCStatsVerifier { : report_(report), stats_(stats), all_tests_successful_(true) { RTC_CHECK(report_); RTC_CHECK(stats_); - for (const RTCStatsMemberInterface* member : stats_->Members()) { - untested_members_.insert(member); + for (const auto& attribute : stats_->Attributes()) { + untested_attribute_names_.insert(attribute.name()); } } - void MarkMemberTested(const RTCStatsMemberInterface& member, - bool test_successful) { - untested_members_.erase(&member); + template + void MarkAttributeTested(const RTCStatsMember& field, + bool test_successful) { + untested_attribute_names_.erase(stats_->GetAttribute(field).name()); all_tests_successful_ &= test_successful; } - void TestMemberIsDefined(const RTCStatsMemberInterface& member) { - EXPECT_TRUE(member.is_defined()) - << stats_->type() << "." << member.name() << "[" << stats_->id() - << "] was undefined."; - MarkMemberTested(member, member.is_defined()); + template + void TestAttributeIsDefined(const RTCStatsMember& field) { + EXPECT_TRUE(field.has_value()) + << stats_->type() << "." << stats_->GetAttribute(field).name() << "[" + << stats_->id() << "] was undefined."; + MarkAttributeTested(field, field.has_value()); } - void TestMemberIsUndefined(const RTCStatsMemberInterface& member) { - EXPECT_FALSE(member.is_defined()) - << stats_->type() << "." << member.name() << "[" << stats_->id() - << "] was defined (" << member.ValueToString() << ")."; - MarkMemberTested(member, !member.is_defined()); + template + void TestAttributeIsUndefined(const RTCStatsMember& field) { + Attribute attribute = stats_->GetAttribute(field); + EXPECT_FALSE(field.has_value()) + << stats_->type() << "." << attribute.name() << "[" << stats_->id() + << "] was defined (" << attribute.ToString() << ")."; + MarkAttributeTested(field, !field.has_value()); } template - void TestMemberIsPositive(const RTCStatsMemberInterface& member) { - EXPECT_TRUE(member.is_defined()) - << stats_->type() << "." << member.name() << "[" << stats_->id() - << "] was undefined."; - if (!member.is_defined()) { - MarkMemberTested(member, false); + void TestAttributeIsPositive(const RTCStatsMember& field) { + Attribute attribute = stats_->GetAttribute(field); + EXPECT_TRUE(field.has_value()) << stats_->type() << "." << attribute.name() + << "[" << stats_->id() << "] was undefined."; + if (!field.has_value()) { + MarkAttributeTested(field, false); return; } - bool is_positive = *member.cast_to>() > T(0); + bool is_positive = field.value() > T(0); EXPECT_TRUE(is_positive) - << stats_->type() << "." << member.name() << "[" << stats_->id() - << "] was not positive (" << member.ValueToString() << ")."; - MarkMemberTested(member, is_positive); + << stats_->type() << "." << attribute.name() << "[" << stats_->id() + << "] was not positive (" << attribute.ToString() << ")."; + MarkAttributeTested(field, is_positive); } template - void TestMemberIsNonNegative(const RTCStatsMemberInterface& member) { - EXPECT_TRUE(member.is_defined()) - << stats_->type() << "." << member.name() << "[" << stats_->id() - << "] was undefined."; - if (!member.is_defined()) { - MarkMemberTested(member, false); + void TestAttributeIsNonNegative(const RTCStatsMember& field) { + Attribute attribute = stats_->GetAttribute(field); + EXPECT_TRUE(field.has_value()) << stats_->type() << "." << attribute.name() + << "[" << stats_->id() << "] was undefined."; + if (!field.has_value()) { + MarkAttributeTested(field, false); return; } - bool is_non_negative = *member.cast_to>() >= T(0); + bool is_non_negative = field.value() >= T(0); EXPECT_TRUE(is_non_negative) - << stats_->type() << "." << member.name() << "[" << stats_->id() - << "] was not non-negative (" << member.ValueToString() << ")."; - MarkMemberTested(member, is_non_negative); + << stats_->type() << "." << attribute.name() << "[" << stats_->id() + << "] was not non-negative (" << attribute.ToString() << ")."; + MarkAttributeTested(field, is_non_negative); } - void TestMemberIsIDReference(const RTCStatsMemberInterface& member, - const char* expected_type) { - TestMemberIsIDReference(member, expected_type, false); + template + void TestAttributeIsIDReference(const RTCStatsMember& field, + const char* expected_type) { + TestAttributeIsIDReference(field, expected_type, false); } - void TestMemberIsOptionalIDReference(const RTCStatsMemberInterface& member, - const char* expected_type) { - TestMemberIsIDReference(member, expected_type, true); + template + void TestAttributeIsOptionalIDReference(const RTCStatsMember& field, + const char* expected_type) { + TestAttributeIsIDReference(field, expected_type, true); } - bool ExpectAllMembersSuccessfullyTested() { - if (untested_members_.empty()) + bool ExpectAllAttributesSuccessfullyTested() { + if (untested_attribute_names_.empty()) return all_tests_successful_; - for (const RTCStatsMemberInterface* member : untested_members_) { - EXPECT_TRUE(false) << stats_->type() << "." << member->name() << "[" - << stats_->id() << "] was not tested."; + for (const char* name : untested_attribute_names_) { + EXPECT_TRUE(false) << stats_->type() << "." << name << "[" << stats_->id() + << "] was not tested."; } return false; } private: - void TestMemberIsIDReference(const RTCStatsMemberInterface& member, - const char* expected_type, - bool optional) { - if (optional && !member.is_defined()) { - MarkMemberTested(member, true); + template + void TestAttributeIsIDReference(const RTCStatsMember& field, + const char* expected_type, + bool optional) { + if (optional && !field.has_value()) { + MarkAttributeTested(field, true); return; } + Attribute attribute = stats_->GetAttribute(field); bool valid_reference = false; - if (member.is_defined()) { - if (member.type() == RTCStatsMemberInterface::kString) { + if (attribute.has_value()) { + if (attribute.holds_alternative()) { // A single ID. - const RTCStatsMember& id = - member.cast_to>(); - const RTCStats* referenced_stats = report_->Get(*id); + const RTCStats* referenced_stats = + report_->Get(attribute.get()); valid_reference = referenced_stats && referenced_stats->type() == expected_type; - } else if (member.type() == RTCStatsMemberInterface::kSequenceString) { + } else if (attribute.holds_alternative>()) { // A vector of IDs. valid_reference = true; - const RTCStatsMember>& ids = - member.cast_to>>(); - for (const std::string& id : *ids) { + for (const std::string& id : + attribute.get>()) { const RTCStats* referenced_stats = report_->Get(id); if (!referenced_stats || referenced_stats->type() != expected_type) { valid_reference = false; @@ -315,17 +321,16 @@ class RTCStatsVerifier { } } EXPECT_TRUE(valid_reference) - << stats_->type() << "." << member.name() + << stats_->type() << "." << attribute.name() << " is not a reference to an " "existing dictionary of type " - << expected_type << " (value: " - << (member.is_defined() ? member.ValueToString() : "null") << ")."; - MarkMemberTested(member, valid_reference); + << expected_type << " (value: " << attribute.ToString() << ")."; + MarkAttributeTested(field, valid_reference); } rtc::scoped_refptr report_; const RTCStats* stats_; - std::set untested_members_; + std::set untested_attribute_names_; bool all_tests_successful_; }; @@ -429,122 +434,129 @@ class RTCStatsReportVerifier { bool VerifyRTCCertificateStats(const RTCCertificateStats& certificate) { RTCStatsVerifier verifier(report_.get(), &certificate); - verifier.TestMemberIsDefined(certificate.fingerprint); - verifier.TestMemberIsDefined(certificate.fingerprint_algorithm); - verifier.TestMemberIsDefined(certificate.base64_certificate); - verifier.TestMemberIsOptionalIDReference(certificate.issuer_certificate_id, - RTCCertificateStats::kType); - return verifier.ExpectAllMembersSuccessfullyTested(); + verifier.TestAttributeIsDefined(certificate.fingerprint); + verifier.TestAttributeIsDefined(certificate.fingerprint_algorithm); + verifier.TestAttributeIsDefined(certificate.base64_certificate); + verifier.TestAttributeIsOptionalIDReference( + certificate.issuer_certificate_id, RTCCertificateStats::kType); + return verifier.ExpectAllAttributesSuccessfullyTested(); } bool VerifyRTCCodecStats(const RTCCodecStats& codec) { RTCStatsVerifier verifier(report_.get(), &codec); - verifier.TestMemberIsIDReference(codec.transport_id, - RTCTransportStats::kType); - verifier.TestMemberIsDefined(codec.payload_type); - verifier.TestMemberIsDefined(codec.mime_type); - verifier.TestMemberIsPositive(codec.clock_rate); + verifier.TestAttributeIsIDReference(codec.transport_id, + RTCTransportStats::kType); + verifier.TestAttributeIsDefined(codec.payload_type); + verifier.TestAttributeIsDefined(codec.mime_type); + verifier.TestAttributeIsPositive(codec.clock_rate); if (codec.mime_type->rfind("audio", 0) == 0) - verifier.TestMemberIsPositive(codec.channels); + verifier.TestAttributeIsPositive(codec.channels); else - verifier.TestMemberIsUndefined(codec.channels); + verifier.TestAttributeIsUndefined(codec.channels); // sdp_fmtp_line is an optional field. - verifier.MarkMemberTested(codec.sdp_fmtp_line, true); - return verifier.ExpectAllMembersSuccessfullyTested(); + verifier.MarkAttributeTested(codec.sdp_fmtp_line, true); + return verifier.ExpectAllAttributesSuccessfullyTested(); } bool VerifyRTCDataChannelStats(const RTCDataChannelStats& data_channel) { RTCStatsVerifier verifier(report_.get(), &data_channel); - verifier.TestMemberIsDefined(data_channel.label); - verifier.TestMemberIsDefined(data_channel.protocol); - verifier.TestMemberIsDefined(data_channel.data_channel_identifier); - verifier.TestMemberIsDefined(data_channel.state); - verifier.TestMemberIsNonNegative(data_channel.messages_sent); - verifier.TestMemberIsNonNegative(data_channel.bytes_sent); - verifier.TestMemberIsNonNegative(data_channel.messages_received); - verifier.TestMemberIsNonNegative(data_channel.bytes_received); - return verifier.ExpectAllMembersSuccessfullyTested(); + verifier.TestAttributeIsDefined(data_channel.label); + verifier.TestAttributeIsDefined(data_channel.protocol); + verifier.TestAttributeIsDefined(data_channel.data_channel_identifier); + verifier.TestAttributeIsDefined(data_channel.state); + verifier.TestAttributeIsNonNegative(data_channel.messages_sent); + verifier.TestAttributeIsNonNegative(data_channel.bytes_sent); + verifier.TestAttributeIsNonNegative( + data_channel.messages_received); + verifier.TestAttributeIsNonNegative(data_channel.bytes_received); + return verifier.ExpectAllAttributesSuccessfullyTested(); } bool VerifyRTCIceCandidatePairStats( const RTCIceCandidatePairStats& candidate_pair, bool is_selected_pair) { RTCStatsVerifier verifier(report_.get(), &candidate_pair); - verifier.TestMemberIsIDReference(candidate_pair.transport_id, - RTCTransportStats::kType); - verifier.TestMemberIsIDReference(candidate_pair.local_candidate_id, - RTCLocalIceCandidateStats::kType); - verifier.TestMemberIsIDReference(candidate_pair.remote_candidate_id, - RTCRemoteIceCandidateStats::kType); - verifier.TestMemberIsDefined(candidate_pair.state); - verifier.TestMemberIsNonNegative(candidate_pair.priority); - verifier.TestMemberIsDefined(candidate_pair.nominated); - verifier.TestMemberIsDefined(candidate_pair.writable); - verifier.TestMemberIsNonNegative(candidate_pair.packets_sent); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsIDReference(candidate_pair.transport_id, + RTCTransportStats::kType); + verifier.TestAttributeIsIDReference(candidate_pair.local_candidate_id, + RTCLocalIceCandidateStats::kType); + verifier.TestAttributeIsIDReference(candidate_pair.remote_candidate_id, + RTCRemoteIceCandidateStats::kType); + verifier.TestAttributeIsDefined(candidate_pair.state); + verifier.TestAttributeIsNonNegative(candidate_pair.priority); + verifier.TestAttributeIsDefined(candidate_pair.nominated); + verifier.TestAttributeIsDefined(candidate_pair.writable); + verifier.TestAttributeIsNonNegative(candidate_pair.packets_sent); + verifier.TestAttributeIsNonNegative( candidate_pair.packets_discarded_on_send); - verifier.TestMemberIsNonNegative(candidate_pair.packets_received); - verifier.TestMemberIsNonNegative(candidate_pair.bytes_sent); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( + candidate_pair.packets_received); + verifier.TestAttributeIsNonNegative(candidate_pair.bytes_sent); + verifier.TestAttributeIsNonNegative( candidate_pair.bytes_discarded_on_send); - verifier.TestMemberIsNonNegative(candidate_pair.bytes_received); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( + candidate_pair.bytes_received); + verifier.TestAttributeIsNonNegative( candidate_pair.total_round_trip_time); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( candidate_pair.current_round_trip_time); if (is_selected_pair) { - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( candidate_pair.available_outgoing_bitrate); // A pair should be nominated in order to be selected. EXPECT_TRUE(*candidate_pair.nominated); } else { - verifier.TestMemberIsUndefined(candidate_pair.available_outgoing_bitrate); + verifier.TestAttributeIsUndefined( + candidate_pair.available_outgoing_bitrate); } - verifier.TestMemberIsUndefined(candidate_pair.available_incoming_bitrate); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsUndefined( + candidate_pair.available_incoming_bitrate); + verifier.TestAttributeIsNonNegative( candidate_pair.requests_received); - verifier.TestMemberIsNonNegative(candidate_pair.requests_sent); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative(candidate_pair.requests_sent); + verifier.TestAttributeIsNonNegative( candidate_pair.responses_received); - verifier.TestMemberIsNonNegative(candidate_pair.responses_sent); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( + candidate_pair.responses_sent); + verifier.TestAttributeIsNonNegative( candidate_pair.consent_requests_sent); - verifier.TestMemberIsDefined(candidate_pair.last_packet_received_timestamp); - verifier.TestMemberIsDefined(candidate_pair.last_packet_sent_timestamp); + verifier.TestAttributeIsDefined( + candidate_pair.last_packet_received_timestamp); + verifier.TestAttributeIsDefined(candidate_pair.last_packet_sent_timestamp); - return verifier.ExpectAllMembersSuccessfullyTested(); + return verifier.ExpectAllAttributesSuccessfullyTested(); } bool VerifyRTCIceCandidateStats(const RTCIceCandidateStats& candidate) { RTCStatsVerifier verifier(report_.get(), &candidate); - verifier.TestMemberIsIDReference(candidate.transport_id, - RTCTransportStats::kType); - verifier.TestMemberIsDefined(candidate.is_remote); + verifier.TestAttributeIsIDReference(candidate.transport_id, + RTCTransportStats::kType); + verifier.TestAttributeIsDefined(candidate.is_remote); if (*candidate.is_remote) { - verifier.TestMemberIsUndefined(candidate.network_type); - verifier.TestMemberIsUndefined(candidate.network_adapter_type); - verifier.TestMemberIsUndefined(candidate.vpn); + verifier.TestAttributeIsUndefined(candidate.network_type); + verifier.TestAttributeIsUndefined(candidate.network_adapter_type); + verifier.TestAttributeIsUndefined(candidate.vpn); } else { - verifier.TestMemberIsDefined(candidate.network_type); - verifier.TestMemberIsDefined(candidate.network_adapter_type); - verifier.TestMemberIsDefined(candidate.vpn); + verifier.TestAttributeIsDefined(candidate.network_type); + verifier.TestAttributeIsDefined(candidate.network_adapter_type); + verifier.TestAttributeIsDefined(candidate.vpn); } - verifier.TestMemberIsDefined(candidate.ip); - verifier.TestMemberIsDefined(candidate.address); - verifier.TestMemberIsNonNegative(candidate.port); - verifier.TestMemberIsDefined(candidate.protocol); - verifier.TestMemberIsDefined(candidate.candidate_type); - verifier.TestMemberIsNonNegative(candidate.priority); - verifier.TestMemberIsUndefined(candidate.url); - verifier.TestMemberIsUndefined(candidate.relay_protocol); - verifier.TestMemberIsDefined(candidate.foundation); - verifier.TestMemberIsUndefined(candidate.related_address); - verifier.TestMemberIsUndefined(candidate.related_port); - verifier.TestMemberIsDefined(candidate.username_fragment); - verifier.TestMemberIsUndefined(candidate.tcp_type); - return verifier.ExpectAllMembersSuccessfullyTested(); + verifier.TestAttributeIsDefined(candidate.ip); + verifier.TestAttributeIsDefined(candidate.address); + verifier.TestAttributeIsNonNegative(candidate.port); + verifier.TestAttributeIsDefined(candidate.protocol); + verifier.TestAttributeIsDefined(candidate.candidate_type); + verifier.TestAttributeIsNonNegative(candidate.priority); + verifier.TestAttributeIsUndefined(candidate.url); + verifier.TestAttributeIsUndefined(candidate.relay_protocol); + verifier.TestAttributeIsDefined(candidate.foundation); + verifier.TestAttributeIsUndefined(candidate.related_address); + verifier.TestAttributeIsUndefined(candidate.related_port); + verifier.TestAttributeIsDefined(candidate.username_fragment); + verifier.TestAttributeIsUndefined(candidate.tcp_type); + return verifier.ExpectAllAttributesSuccessfullyTested(); } bool VerifyRTCLocalIceCandidateStats( @@ -560,226 +572,235 @@ class RTCStatsReportVerifier { bool VerifyRTCPeerConnectionStats( const RTCPeerConnectionStats& peer_connection) { RTCStatsVerifier verifier(report_.get(), &peer_connection); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( peer_connection.data_channels_opened); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( peer_connection.data_channels_closed); - return verifier.ExpectAllMembersSuccessfullyTested(); + return verifier.ExpectAllAttributesSuccessfullyTested(); } void VerifyRTCRtpStreamStats(const RTCRtpStreamStats& stream, RTCStatsVerifier& verifier) { - verifier.TestMemberIsDefined(stream.ssrc); - verifier.TestMemberIsDefined(stream.kind); - verifier.TestMemberIsIDReference(stream.transport_id, - RTCTransportStats::kType); - verifier.TestMemberIsIDReference(stream.codec_id, RTCCodecStats::kType); + verifier.TestAttributeIsDefined(stream.ssrc); + verifier.TestAttributeIsDefined(stream.kind); + verifier.TestAttributeIsIDReference(stream.transport_id, + RTCTransportStats::kType); + verifier.TestAttributeIsIDReference(stream.codec_id, RTCCodecStats::kType); } void VerifyRTCSentRtpStreamStats(const RTCSentRtpStreamStats& sent_stream, RTCStatsVerifier& verifier) { VerifyRTCRtpStreamStats(sent_stream, verifier); - verifier.TestMemberIsNonNegative(sent_stream.packets_sent); - verifier.TestMemberIsNonNegative(sent_stream.bytes_sent); + verifier.TestAttributeIsNonNegative(sent_stream.packets_sent); + verifier.TestAttributeIsNonNegative(sent_stream.bytes_sent); } bool VerifyRTCInboundRtpStreamStats( const RTCInboundRtpStreamStats& inbound_stream) { RTCStatsVerifier verifier(report_.get(), &inbound_stream); VerifyRTCReceivedRtpStreamStats(inbound_stream, verifier); - verifier.TestMemberIsOptionalIDReference( + verifier.TestAttributeIsOptionalIDReference( inbound_stream.remote_id, RTCRemoteOutboundRtpStreamStats::kType); - verifier.TestMemberIsDefined(inbound_stream.mid); - verifier.TestMemberIsDefined(inbound_stream.track_identifier); - if (inbound_stream.kind.is_defined() && *inbound_stream.kind == "video") { - verifier.TestMemberIsNonNegative(inbound_stream.qp_sum); - verifier.TestMemberIsDefined(inbound_stream.decoder_implementation); - verifier.TestMemberIsDefined(inbound_stream.power_efficient_decoder); + verifier.TestAttributeIsDefined(inbound_stream.mid); + verifier.TestAttributeIsDefined(inbound_stream.track_identifier); + if (inbound_stream.kind.has_value() && *inbound_stream.kind == "video") { + verifier.TestAttributeIsNonNegative(inbound_stream.qp_sum); + verifier.TestAttributeIsDefined(inbound_stream.decoder_implementation); + verifier.TestAttributeIsDefined(inbound_stream.power_efficient_decoder); } else { - verifier.TestMemberIsUndefined(inbound_stream.qp_sum); - verifier.TestMemberIsUndefined(inbound_stream.decoder_implementation); - verifier.TestMemberIsUndefined(inbound_stream.power_efficient_decoder); + verifier.TestAttributeIsUndefined(inbound_stream.qp_sum); + verifier.TestAttributeIsUndefined(inbound_stream.decoder_implementation); + verifier.TestAttributeIsUndefined(inbound_stream.power_efficient_decoder); } - verifier.TestMemberIsNonNegative(inbound_stream.packets_received); - if (inbound_stream.kind.is_defined() && *inbound_stream.kind == "audio") { - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( + inbound_stream.packets_received); + if (inbound_stream.kind.has_value() && *inbound_stream.kind == "audio") { + verifier.TestAttributeIsNonNegative( inbound_stream.packets_discarded); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( inbound_stream.fec_packets_received); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( inbound_stream.fec_packets_discarded); - verifier.TestMemberIsUndefined(inbound_stream.fec_bytes_received); + verifier.TestAttributeIsUndefined(inbound_stream.fec_bytes_received); } else { - verifier.TestMemberIsUndefined(inbound_stream.packets_discarded); + verifier.TestAttributeIsUndefined(inbound_stream.packets_discarded); // FEC stats are only present when FlexFEC was negotiated which is guarded // by the WebRTC-FlexFEC-03-Advertised/Enabled/ field trial and off by // default. - verifier.TestMemberIsUndefined(inbound_stream.fec_bytes_received); - verifier.TestMemberIsUndefined(inbound_stream.fec_packets_received); - verifier.TestMemberIsUndefined(inbound_stream.fec_packets_discarded); - verifier.TestMemberIsUndefined(inbound_stream.fec_ssrc); + verifier.TestAttributeIsUndefined(inbound_stream.fec_bytes_received); + verifier.TestAttributeIsUndefined(inbound_stream.fec_packets_received); + verifier.TestAttributeIsUndefined(inbound_stream.fec_packets_discarded); + verifier.TestAttributeIsUndefined(inbound_stream.fec_ssrc); } - verifier.TestMemberIsNonNegative(inbound_stream.bytes_received); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( + inbound_stream.bytes_received); + verifier.TestAttributeIsNonNegative( inbound_stream.header_bytes_received); - verifier.TestMemberIsDefined(inbound_stream.last_packet_received_timestamp); - if (inbound_stream.frames_received.ValueOrDefault(0) > 0) { - verifier.TestMemberIsNonNegative(inbound_stream.frame_width); - verifier.TestMemberIsNonNegative(inbound_stream.frame_height); + verifier.TestAttributeIsDefined( + inbound_stream.last_packet_received_timestamp); + if (inbound_stream.frames_received.value_or(0) > 0) { + verifier.TestAttributeIsNonNegative(inbound_stream.frame_width); + verifier.TestAttributeIsNonNegative( + inbound_stream.frame_height); } else { - verifier.TestMemberIsUndefined(inbound_stream.frame_width); - verifier.TestMemberIsUndefined(inbound_stream.frame_height); + verifier.TestAttributeIsUndefined(inbound_stream.frame_width); + verifier.TestAttributeIsUndefined(inbound_stream.frame_height); } - if (inbound_stream.frames_per_second.is_defined()) { - verifier.TestMemberIsNonNegative( + if (inbound_stream.frames_per_second.has_value()) { + verifier.TestAttributeIsNonNegative( inbound_stream.frames_per_second); } else { - verifier.TestMemberIsUndefined(inbound_stream.frames_per_second); + verifier.TestAttributeIsUndefined(inbound_stream.frames_per_second); } - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( inbound_stream.jitter_buffer_delay); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( inbound_stream.jitter_buffer_emitted_count); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( inbound_stream.jitter_buffer_target_delay); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( inbound_stream.jitter_buffer_minimum_delay); - if (inbound_stream.kind.is_defined() && *inbound_stream.kind == "video") { - verifier.TestMemberIsUndefined(inbound_stream.total_samples_received); - verifier.TestMemberIsUndefined(inbound_stream.concealed_samples); - verifier.TestMemberIsUndefined(inbound_stream.silent_concealed_samples); - verifier.TestMemberIsUndefined(inbound_stream.concealment_events); - verifier.TestMemberIsUndefined( + if (inbound_stream.kind.has_value() && *inbound_stream.kind == "video") { + verifier.TestAttributeIsUndefined(inbound_stream.total_samples_received); + verifier.TestAttributeIsUndefined(inbound_stream.concealed_samples); + verifier.TestAttributeIsUndefined( + inbound_stream.silent_concealed_samples); + verifier.TestAttributeIsUndefined(inbound_stream.concealment_events); + verifier.TestAttributeIsUndefined( inbound_stream.inserted_samples_for_deceleration); - verifier.TestMemberIsUndefined( + verifier.TestAttributeIsUndefined( inbound_stream.removed_samples_for_acceleration); - verifier.TestMemberIsUndefined(inbound_stream.audio_level); - verifier.TestMemberIsUndefined(inbound_stream.total_audio_energy); - verifier.TestMemberIsUndefined(inbound_stream.total_samples_duration); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsUndefined(inbound_stream.audio_level); + verifier.TestAttributeIsUndefined(inbound_stream.total_audio_energy); + verifier.TestAttributeIsUndefined(inbound_stream.total_samples_duration); + verifier.TestAttributeIsNonNegative( inbound_stream.frames_received); - verifier.TestMemberIsNonNegative(inbound_stream.fir_count); - verifier.TestMemberIsNonNegative(inbound_stream.pli_count); - verifier.TestMemberIsNonNegative(inbound_stream.nack_count); + verifier.TestAttributeIsNonNegative(inbound_stream.fir_count); + verifier.TestAttributeIsNonNegative(inbound_stream.pli_count); + verifier.TestAttributeIsNonNegative(inbound_stream.nack_count); } else { - verifier.TestMemberIsUndefined(inbound_stream.fir_count); - verifier.TestMemberIsUndefined(inbound_stream.pli_count); - verifier.TestMemberIsUndefined(inbound_stream.nack_count); - verifier.TestMemberIsPositive( + verifier.TestAttributeIsUndefined(inbound_stream.fir_count); + verifier.TestAttributeIsUndefined(inbound_stream.pli_count); + verifier.TestAttributeIsUndefined(inbound_stream.nack_count); + verifier.TestAttributeIsPositive( inbound_stream.total_samples_received); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( inbound_stream.concealed_samples); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( inbound_stream.silent_concealed_samples); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( inbound_stream.concealment_events); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( inbound_stream.inserted_samples_for_deceleration); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( inbound_stream.removed_samples_for_acceleration); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( inbound_stream.jitter_buffer_target_delay); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( inbound_stream.jitter_buffer_minimum_delay); - verifier.TestMemberIsPositive(inbound_stream.audio_level); - verifier.TestMemberIsPositive(inbound_stream.total_audio_energy); - verifier.TestMemberIsPositive( + verifier.TestAttributeIsPositive(inbound_stream.audio_level); + verifier.TestAttributeIsPositive( + inbound_stream.total_audio_energy); + verifier.TestAttributeIsPositive( inbound_stream.total_samples_duration); - verifier.TestMemberIsUndefined(inbound_stream.frames_received); + verifier.TestAttributeIsUndefined(inbound_stream.frames_received); } // RTX stats are typically only defined for video where RTX is negotiated. - if (inbound_stream.kind.is_defined() && *inbound_stream.kind == "video") { - verifier.TestMemberIsNonNegative( + if (inbound_stream.kind.has_value() && *inbound_stream.kind == "video") { + verifier.TestAttributeIsNonNegative( inbound_stream.retransmitted_packets_received); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( inbound_stream.retransmitted_bytes_received); - verifier.TestMemberIsNonNegative(inbound_stream.rtx_ssrc); + verifier.TestAttributeIsNonNegative(inbound_stream.rtx_ssrc); } else { - verifier.TestMemberIsUndefined( + verifier.TestAttributeIsUndefined( inbound_stream.retransmitted_packets_received); - verifier.TestMemberIsUndefined( + verifier.TestAttributeIsUndefined( inbound_stream.retransmitted_bytes_received); - verifier.TestMemberIsUndefined(inbound_stream.rtx_ssrc); - verifier.TestMemberIsUndefined(inbound_stream.fec_ssrc); + verifier.TestAttributeIsUndefined(inbound_stream.rtx_ssrc); + verifier.TestAttributeIsUndefined(inbound_stream.fec_ssrc); } // Test runtime too short to get an estimate (at least two RTCP sender // reports need to be received). - verifier.MarkMemberTested(inbound_stream.estimated_playout_timestamp, true); - if (inbound_stream.kind.is_defined() && *inbound_stream.kind == "video") { - verifier.TestMemberIsDefined(inbound_stream.frames_decoded); - verifier.TestMemberIsDefined(inbound_stream.key_frames_decoded); - verifier.TestMemberIsNonNegative(inbound_stream.frames_dropped); - verifier.TestMemberIsNonNegative( + verifier.MarkAttributeTested(inbound_stream.estimated_playout_timestamp, + true); + if (inbound_stream.kind.has_value() && *inbound_stream.kind == "video") { + verifier.TestAttributeIsDefined(inbound_stream.frames_decoded); + verifier.TestAttributeIsDefined(inbound_stream.key_frames_decoded); + verifier.TestAttributeIsNonNegative( + inbound_stream.frames_dropped); + verifier.TestAttributeIsNonNegative( inbound_stream.total_decode_time); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( inbound_stream.total_processing_delay); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( inbound_stream.total_assembly_time); - verifier.TestMemberIsDefined( + verifier.TestAttributeIsDefined( inbound_stream.frames_assembled_from_multiple_packets); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( inbound_stream.total_inter_frame_delay); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( inbound_stream.total_squared_inter_frame_delay); - verifier.TestMemberIsNonNegative(inbound_stream.pause_count); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative(inbound_stream.pause_count); + verifier.TestAttributeIsNonNegative( inbound_stream.total_pauses_duration); - verifier.TestMemberIsNonNegative(inbound_stream.freeze_count); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( + inbound_stream.freeze_count); + verifier.TestAttributeIsNonNegative( inbound_stream.total_freezes_duration); // The integration test is not set up to test screen share; don't require // this to be present. - verifier.MarkMemberTested(inbound_stream.content_type, true); - verifier.TestMemberIsUndefined(inbound_stream.jitter_buffer_flushes); - verifier.TestMemberIsUndefined( + verifier.MarkAttributeTested(inbound_stream.content_type, true); + verifier.TestAttributeIsUndefined(inbound_stream.jitter_buffer_flushes); + verifier.TestAttributeIsUndefined( inbound_stream.delayed_packet_outage_samples); - verifier.TestMemberIsUndefined( + verifier.TestAttributeIsUndefined( inbound_stream.relative_packet_arrival_delay); - verifier.TestMemberIsUndefined(inbound_stream.interruption_count); - verifier.TestMemberIsUndefined( + verifier.TestAttributeIsUndefined(inbound_stream.interruption_count); + verifier.TestAttributeIsUndefined( inbound_stream.total_interruption_duration); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( inbound_stream.min_playout_delay); - verifier.TestMemberIsDefined(inbound_stream.goog_timing_frame_info); + verifier.TestAttributeIsDefined(inbound_stream.goog_timing_frame_info); } else { - verifier.TestMemberIsUndefined(inbound_stream.frames_decoded); - verifier.TestMemberIsUndefined(inbound_stream.key_frames_decoded); - verifier.TestMemberIsUndefined(inbound_stream.frames_dropped); - verifier.TestMemberIsUndefined(inbound_stream.total_decode_time); - verifier.TestMemberIsUndefined(inbound_stream.total_processing_delay); - verifier.TestMemberIsUndefined(inbound_stream.total_assembly_time); - verifier.TestMemberIsUndefined( + verifier.TestAttributeIsUndefined(inbound_stream.frames_decoded); + verifier.TestAttributeIsUndefined(inbound_stream.key_frames_decoded); + verifier.TestAttributeIsUndefined(inbound_stream.frames_dropped); + verifier.TestAttributeIsUndefined(inbound_stream.total_decode_time); + verifier.TestAttributeIsUndefined(inbound_stream.total_processing_delay); + verifier.TestAttributeIsUndefined(inbound_stream.total_assembly_time); + verifier.TestAttributeIsUndefined( inbound_stream.frames_assembled_from_multiple_packets); - verifier.TestMemberIsUndefined(inbound_stream.total_inter_frame_delay); - verifier.TestMemberIsUndefined( + verifier.TestAttributeIsUndefined(inbound_stream.total_inter_frame_delay); + verifier.TestAttributeIsUndefined( inbound_stream.total_squared_inter_frame_delay); - verifier.TestMemberIsUndefined(inbound_stream.pause_count); - verifier.TestMemberIsUndefined(inbound_stream.total_pauses_duration); - verifier.TestMemberIsUndefined(inbound_stream.freeze_count); - verifier.TestMemberIsUndefined(inbound_stream.total_freezes_duration); - verifier.TestMemberIsUndefined(inbound_stream.content_type); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsUndefined(inbound_stream.pause_count); + verifier.TestAttributeIsUndefined(inbound_stream.total_pauses_duration); + verifier.TestAttributeIsUndefined(inbound_stream.freeze_count); + verifier.TestAttributeIsUndefined(inbound_stream.total_freezes_duration); + verifier.TestAttributeIsUndefined(inbound_stream.content_type); + verifier.TestAttributeIsNonNegative( inbound_stream.jitter_buffer_flushes); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( inbound_stream.delayed_packet_outage_samples); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( inbound_stream.relative_packet_arrival_delay); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( inbound_stream.interruption_count); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( inbound_stream.total_interruption_duration); - verifier.TestMemberIsUndefined(inbound_stream.min_playout_delay); - verifier.TestMemberIsUndefined(inbound_stream.goog_timing_frame_info); + verifier.TestAttributeIsUndefined(inbound_stream.min_playout_delay); + verifier.TestAttributeIsUndefined(inbound_stream.goog_timing_frame_info); } - if (inbound_stream.kind.is_defined() && *inbound_stream.kind == "audio") { - verifier.TestMemberIsDefined(inbound_stream.playout_id); + if (inbound_stream.kind.has_value() && *inbound_stream.kind == "audio") { + verifier.TestAttributeIsDefined(inbound_stream.playout_id); } else { - verifier.TestMemberIsUndefined(inbound_stream.playout_id); + verifier.TestAttributeIsUndefined(inbound_stream.playout_id); } - return verifier.ExpectAllMembersSuccessfullyTested(); + return verifier.ExpectAllAttributesSuccessfullyTested(); } bool VerifyRTCOutboundRtpStreamStats( @@ -787,122 +808,128 @@ class RTCStatsReportVerifier { RTCStatsVerifier verifier(report_.get(), &outbound_stream); VerifyRTCSentRtpStreamStats(outbound_stream, verifier); - verifier.TestMemberIsDefined(outbound_stream.mid); - verifier.TestMemberIsDefined(outbound_stream.active); - if (outbound_stream.kind.is_defined() && *outbound_stream.kind == "video") { - verifier.TestMemberIsIDReference(outbound_stream.media_source_id, - RTCVideoSourceStats::kType); - verifier.TestMemberIsNonNegative(outbound_stream.fir_count); - verifier.TestMemberIsNonNegative(outbound_stream.pli_count); + verifier.TestAttributeIsDefined(outbound_stream.mid); + verifier.TestAttributeIsDefined(outbound_stream.active); + if (outbound_stream.kind.has_value() && *outbound_stream.kind == "video") { + verifier.TestAttributeIsIDReference(outbound_stream.media_source_id, + RTCVideoSourceStats::kType); + verifier.TestAttributeIsNonNegative(outbound_stream.fir_count); + verifier.TestAttributeIsNonNegative(outbound_stream.pli_count); if (*outbound_stream.frames_encoded > 0) { - verifier.TestMemberIsNonNegative(outbound_stream.qp_sum); + verifier.TestAttributeIsNonNegative(outbound_stream.qp_sum); } else { - verifier.TestMemberIsUndefined(outbound_stream.qp_sum); + verifier.TestAttributeIsUndefined(outbound_stream.qp_sum); } } else { - verifier.TestMemberIsUndefined(outbound_stream.fir_count); - verifier.TestMemberIsUndefined(outbound_stream.pli_count); - verifier.TestMemberIsIDReference(outbound_stream.media_source_id, - RTCAudioSourceStats::kType); - verifier.TestMemberIsUndefined(outbound_stream.qp_sum); + verifier.TestAttributeIsUndefined(outbound_stream.fir_count); + verifier.TestAttributeIsUndefined(outbound_stream.pli_count); + verifier.TestAttributeIsIDReference(outbound_stream.media_source_id, + RTCAudioSourceStats::kType); + verifier.TestAttributeIsUndefined(outbound_stream.qp_sum); } - verifier.TestMemberIsNonNegative(outbound_stream.nack_count); - verifier.TestMemberIsOptionalIDReference( + verifier.TestAttributeIsNonNegative(outbound_stream.nack_count); + verifier.TestAttributeIsOptionalIDReference( outbound_stream.remote_id, RTCRemoteInboundRtpStreamStats::kType); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( outbound_stream.total_packet_send_delay); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( outbound_stream.retransmitted_packets_sent); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( outbound_stream.header_bytes_sent); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( outbound_stream.retransmitted_bytes_sent); - verifier.TestMemberIsNonNegative(outbound_stream.target_bitrate); - if (outbound_stream.kind.is_defined() && *outbound_stream.kind == "video") { - verifier.TestMemberIsDefined(outbound_stream.frames_encoded); - verifier.TestMemberIsDefined(outbound_stream.key_frames_encoded); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative(outbound_stream.target_bitrate); + if (outbound_stream.kind.has_value() && *outbound_stream.kind == "video") { + verifier.TestAttributeIsDefined(outbound_stream.frames_encoded); + verifier.TestAttributeIsDefined(outbound_stream.key_frames_encoded); + verifier.TestAttributeIsNonNegative( outbound_stream.total_encode_time); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( outbound_stream.total_encoded_bytes_target); - verifier.TestMemberIsDefined(outbound_stream.quality_limitation_reason); - verifier.TestMemberIsDefined( + verifier.TestAttributeIsDefined( + outbound_stream.quality_limitation_reason); + verifier.TestAttributeIsDefined( outbound_stream.quality_limitation_durations); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( outbound_stream.quality_limitation_resolution_changes); // The integration test is not set up to test screen share; don't require // this to be present. - verifier.MarkMemberTested(outbound_stream.content_type, true); - verifier.TestMemberIsDefined(outbound_stream.encoder_implementation); - verifier.TestMemberIsDefined(outbound_stream.power_efficient_encoder); + verifier.MarkAttributeTested(outbound_stream.content_type, true); + verifier.TestAttributeIsDefined(outbound_stream.encoder_implementation); + verifier.TestAttributeIsDefined(outbound_stream.power_efficient_encoder); // Unless an implementation-specific amount of time has passed and at // least one frame has been encoded, undefined is reported. Because it // is hard to tell what is the case here, we treat FPS as optional. // TODO(hbos): Update the tests to run until all implemented metrics // should be populated. - if (outbound_stream.frames_per_second.is_defined()) { - verifier.TestMemberIsNonNegative( + if (outbound_stream.frames_per_second.has_value()) { + verifier.TestAttributeIsNonNegative( outbound_stream.frames_per_second); } else { - verifier.TestMemberIsUndefined(outbound_stream.frames_per_second); + verifier.TestAttributeIsUndefined(outbound_stream.frames_per_second); } - verifier.TestMemberIsNonNegative(outbound_stream.frame_height); - verifier.TestMemberIsNonNegative(outbound_stream.frame_width); - verifier.TestMemberIsNonNegative(outbound_stream.frames_sent); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( + outbound_stream.frame_height); + verifier.TestAttributeIsNonNegative( + outbound_stream.frame_width); + verifier.TestAttributeIsNonNegative( + outbound_stream.frames_sent); + verifier.TestAttributeIsNonNegative( outbound_stream.huge_frames_sent); - verifier.MarkMemberTested(outbound_stream.rid, true); - verifier.TestMemberIsDefined(outbound_stream.scalability_mode); - verifier.TestMemberIsNonNegative(outbound_stream.rtx_ssrc); + verifier.MarkAttributeTested(outbound_stream.rid, true); + verifier.TestAttributeIsDefined(outbound_stream.scalability_mode); + verifier.TestAttributeIsNonNegative(outbound_stream.rtx_ssrc); } else { - verifier.TestMemberIsUndefined(outbound_stream.frames_encoded); - verifier.TestMemberIsUndefined(outbound_stream.key_frames_encoded); - verifier.TestMemberIsUndefined(outbound_stream.total_encode_time); - verifier.TestMemberIsUndefined( + verifier.TestAttributeIsUndefined(outbound_stream.frames_encoded); + verifier.TestAttributeIsUndefined(outbound_stream.key_frames_encoded); + verifier.TestAttributeIsUndefined(outbound_stream.total_encode_time); + verifier.TestAttributeIsUndefined( outbound_stream.total_encoded_bytes_target); - verifier.TestMemberIsUndefined(outbound_stream.quality_limitation_reason); - verifier.TestMemberIsUndefined( + verifier.TestAttributeIsUndefined( + outbound_stream.quality_limitation_reason); + verifier.TestAttributeIsUndefined( outbound_stream.quality_limitation_durations); - verifier.TestMemberIsUndefined( + verifier.TestAttributeIsUndefined( outbound_stream.quality_limitation_resolution_changes); - verifier.TestMemberIsUndefined(outbound_stream.content_type); + verifier.TestAttributeIsUndefined(outbound_stream.content_type); // TODO(hbos): Implement for audio as well. - verifier.TestMemberIsUndefined(outbound_stream.encoder_implementation); - verifier.TestMemberIsUndefined(outbound_stream.power_efficient_encoder); - verifier.TestMemberIsUndefined(outbound_stream.rid); - verifier.TestMemberIsUndefined(outbound_stream.frames_per_second); - verifier.TestMemberIsUndefined(outbound_stream.frame_height); - verifier.TestMemberIsUndefined(outbound_stream.frame_width); - verifier.TestMemberIsUndefined(outbound_stream.frames_sent); - verifier.TestMemberIsUndefined(outbound_stream.huge_frames_sent); - verifier.TestMemberIsUndefined(outbound_stream.scalability_mode); - verifier.TestMemberIsUndefined(outbound_stream.rtx_ssrc); + verifier.TestAttributeIsUndefined(outbound_stream.encoder_implementation); + verifier.TestAttributeIsUndefined( + outbound_stream.power_efficient_encoder); + verifier.TestAttributeIsUndefined(outbound_stream.rid); + verifier.TestAttributeIsUndefined(outbound_stream.frames_per_second); + verifier.TestAttributeIsUndefined(outbound_stream.frame_height); + verifier.TestAttributeIsUndefined(outbound_stream.frame_width); + verifier.TestAttributeIsUndefined(outbound_stream.frames_sent); + verifier.TestAttributeIsUndefined(outbound_stream.huge_frames_sent); + verifier.TestAttributeIsUndefined(outbound_stream.scalability_mode); + verifier.TestAttributeIsUndefined(outbound_stream.rtx_ssrc); } - return verifier.ExpectAllMembersSuccessfullyTested(); + return verifier.ExpectAllAttributesSuccessfullyTested(); } void VerifyRTCReceivedRtpStreamStats( const RTCReceivedRtpStreamStats& received_rtp, RTCStatsVerifier& verifier) { VerifyRTCRtpStreamStats(received_rtp, verifier); - verifier.TestMemberIsNonNegative(received_rtp.jitter); - verifier.TestMemberIsDefined(received_rtp.packets_lost); + verifier.TestAttributeIsNonNegative(received_rtp.jitter); + verifier.TestAttributeIsDefined(received_rtp.packets_lost); } bool VerifyRTCRemoteInboundRtpStreamStats( const RTCRemoteInboundRtpStreamStats& remote_inbound_stream) { RTCStatsVerifier verifier(report_.get(), &remote_inbound_stream); VerifyRTCReceivedRtpStreamStats(remote_inbound_stream, verifier); - verifier.TestMemberIsDefined(remote_inbound_stream.fraction_lost); - verifier.TestMemberIsIDReference(remote_inbound_stream.local_id, - RTCOutboundRtpStreamStats::kType); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsDefined(remote_inbound_stream.fraction_lost); + verifier.TestAttributeIsIDReference(remote_inbound_stream.local_id, + RTCOutboundRtpStreamStats::kType); + verifier.TestAttributeIsNonNegative( remote_inbound_stream.round_trip_time); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( remote_inbound_stream.total_round_trip_time); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( remote_inbound_stream.round_trip_time_measurements); - return verifier.ExpectAllMembersSuccessfullyTested(); + return verifier.ExpectAllAttributesSuccessfullyTested(); } bool VerifyRTCRemoteOutboundRtpStreamStats( @@ -910,19 +937,19 @@ class RTCStatsReportVerifier { RTCStatsVerifier verifier(report_.get(), &remote_outbound_stream); VerifyRTCRtpStreamStats(remote_outbound_stream, verifier); VerifyRTCSentRtpStreamStats(remote_outbound_stream, verifier); - verifier.TestMemberIsIDReference(remote_outbound_stream.local_id, - RTCOutboundRtpStreamStats::kType); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsIDReference(remote_outbound_stream.local_id, + RTCOutboundRtpStreamStats::kType); + verifier.TestAttributeIsNonNegative( remote_outbound_stream.remote_timestamp); - verifier.TestMemberIsDefined(remote_outbound_stream.reports_sent); - return verifier.ExpectAllMembersSuccessfullyTested(); + verifier.TestAttributeIsDefined(remote_outbound_stream.reports_sent); + return verifier.ExpectAllAttributesSuccessfullyTested(); } void VerifyRTCMediaSourceStats(const RTCMediaSourceStats& media_source, RTCStatsVerifier* verifier) { - verifier->TestMemberIsDefined(media_source.track_identifier); - verifier->TestMemberIsDefined(media_source.kind); - if (media_source.kind.is_defined()) { + verifier->TestAttributeIsDefined(media_source.track_identifier); + verifier->TestAttributeIsDefined(media_source.kind); + if (media_source.kind.has_value()) { EXPECT_TRUE((*media_source.kind == "audio" && media_source.type() == RTCAudioSourceStats::kType) || (*media_source.kind == "video" && @@ -936,16 +963,18 @@ class RTCStatsReportVerifier { // Audio level, unlike audio energy, only gets updated at a certain // frequency, so we don't require that one to be positive to avoid a race // (https://crbug.com/webrtc/10962). - verifier.TestMemberIsNonNegative(audio_source.audio_level); - verifier.TestMemberIsPositive(audio_source.total_audio_energy); - verifier.TestMemberIsPositive(audio_source.total_samples_duration); + verifier.TestAttributeIsNonNegative(audio_source.audio_level); + verifier.TestAttributeIsPositive(audio_source.total_audio_energy); + verifier.TestAttributeIsPositive( + audio_source.total_samples_duration); // TODO(hbos): `echo_return_loss` and `echo_return_loss_enhancement` are // flaky on msan bot (sometimes defined, sometimes undefined). Should the // test run until available or is there a way to have it always be // defined? crbug.com/627816 - verifier.MarkMemberTested(audio_source.echo_return_loss, true); - verifier.MarkMemberTested(audio_source.echo_return_loss_enhancement, true); - return verifier.ExpectAllMembersSuccessfullyTested(); + verifier.MarkAttributeTested(audio_source.echo_return_loss, true); + verifier.MarkAttributeTested(audio_source.echo_return_loss_enhancement, + true); + return verifier.ExpectAllAttributesSuccessfullyTested(); } bool VerifyRTCVideoSourceStats(const RTCVideoSourceStats& video_source) { @@ -953,58 +982,59 @@ class RTCStatsReportVerifier { VerifyRTCMediaSourceStats(video_source, &verifier); // TODO(hbos): This integration test uses fakes that doesn't support // VideoTrackSourceInterface::Stats. When this is fixed we should - // TestMemberIsNonNegative() for `width` and `height` instead to - // reflect real code. - verifier.TestMemberIsUndefined(video_source.width); - verifier.TestMemberIsUndefined(video_source.height); - verifier.TestMemberIsNonNegative(video_source.frames); - verifier.TestMemberIsNonNegative(video_source.frames_per_second); - return verifier.ExpectAllMembersSuccessfullyTested(); + // TestAttributeIsNonNegative() for `width` and `height` instead + // to reflect real code. + verifier.TestAttributeIsUndefined(video_source.width); + verifier.TestAttributeIsUndefined(video_source.height); + verifier.TestAttributeIsNonNegative(video_source.frames); + verifier.TestAttributeIsNonNegative(video_source.frames_per_second); + return verifier.ExpectAllAttributesSuccessfullyTested(); } bool VerifyRTCTransportStats(const RTCTransportStats& transport) { RTCStatsVerifier verifier(report_.get(), &transport); - verifier.TestMemberIsNonNegative(transport.bytes_sent); - verifier.TestMemberIsNonNegative(transport.packets_sent); - verifier.TestMemberIsNonNegative(transport.bytes_received); - verifier.TestMemberIsNonNegative(transport.packets_received); - verifier.TestMemberIsOptionalIDReference(transport.rtcp_transport_stats_id, - RTCTransportStats::kType); - verifier.TestMemberIsDefined(transport.dtls_state); - verifier.TestMemberIsIDReference(transport.selected_candidate_pair_id, - RTCIceCandidatePairStats::kType); - verifier.TestMemberIsIDReference(transport.local_certificate_id, - RTCCertificateStats::kType); - verifier.TestMemberIsIDReference(transport.remote_certificate_id, - RTCCertificateStats::kType); - verifier.TestMemberIsDefined(transport.tls_version); - verifier.TestMemberIsDefined(transport.dtls_cipher); - verifier.TestMemberIsDefined(transport.dtls_role); - verifier.TestMemberIsDefined(transport.srtp_cipher); - verifier.TestMemberIsPositive( + verifier.TestAttributeIsNonNegative(transport.bytes_sent); + verifier.TestAttributeIsNonNegative(transport.packets_sent); + verifier.TestAttributeIsNonNegative(transport.bytes_received); + verifier.TestAttributeIsNonNegative(transport.packets_received); + verifier.TestAttributeIsOptionalIDReference( + transport.rtcp_transport_stats_id, RTCTransportStats::kType); + verifier.TestAttributeIsDefined(transport.dtls_state); + verifier.TestAttributeIsIDReference(transport.selected_candidate_pair_id, + RTCIceCandidatePairStats::kType); + verifier.TestAttributeIsIDReference(transport.local_certificate_id, + RTCCertificateStats::kType); + verifier.TestAttributeIsIDReference(transport.remote_certificate_id, + RTCCertificateStats::kType); + verifier.TestAttributeIsDefined(transport.tls_version); + verifier.TestAttributeIsDefined(transport.dtls_cipher); + verifier.TestAttributeIsDefined(transport.dtls_role); + verifier.TestAttributeIsDefined(transport.srtp_cipher); + verifier.TestAttributeIsPositive( transport.selected_candidate_pair_changes); - verifier.TestMemberIsDefined(transport.ice_role); - verifier.TestMemberIsDefined(transport.ice_local_username_fragment); - verifier.TestMemberIsDefined(transport.ice_state); - return verifier.ExpectAllMembersSuccessfullyTested(); + verifier.TestAttributeIsDefined(transport.ice_role); + verifier.TestAttributeIsDefined(transport.ice_local_username_fragment); + verifier.TestAttributeIsDefined(transport.ice_state); + return verifier.ExpectAllAttributesSuccessfullyTested(); } bool VerifyRTCAudioPlayoutStats(const RTCAudioPlayoutStats& audio_playout) { RTCStatsVerifier verifier(report_.get(), &audio_playout); - verifier.TestMemberIsDefined(audio_playout.kind); - if (audio_playout.kind.is_defined()) { + verifier.TestAttributeIsDefined(audio_playout.kind); + if (audio_playout.kind.has_value()) { EXPECT_EQ(*audio_playout.kind, "audio"); } - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( audio_playout.synthesized_samples_events); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( audio_playout.synthesized_samples_duration); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( audio_playout.total_samples_count); - verifier.TestMemberIsNonNegative( + verifier.TestAttributeIsNonNegative( audio_playout.total_samples_duration); - verifier.TestMemberIsNonNegative(audio_playout.total_playout_delay); - return verifier.ExpectAllMembersSuccessfullyTested(); + verifier.TestAttributeIsNonNegative( + audio_playout.total_playout_delay); + return verifier.ExpectAllAttributesSuccessfullyTested(); } private: @@ -1034,8 +1064,8 @@ TEST_F(RTCStatsIntegrationTest, GetStatsFromCallee) { auto inbound_stats = report->GetStatsOfType(); return !inbound_stats.empty() && - inbound_stats.front()->round_trip_time.is_defined() && - inbound_stats.front()->round_trip_time_measurements.is_defined(); + inbound_stats.front()->round_trip_time.has_value() && + inbound_stats.front()->round_trip_time_measurements.has_value(); }; EXPECT_TRUE_WAIT(GetStatsReportAndReturnTrueIfRttIsDefined(), kMaxWaitMs); RTCStatsReportVerifier(report.get()).VerifyReport({}); @@ -1142,32 +1172,31 @@ TEST_F(RTCStatsIntegrationTest, GetsStatsWhileClosingPeerConnection) { } // GetStatsReferencedIds() is optimized to recognize what is or isn't a -// referenced ID based on dictionary type information and knowing what members -// are used as references, as opposed to iterating all members to find the ones -// with the "Id" or "Ids" suffix. As such, GetStatsReferencedIds() is tested as -// an integration test instead of a unit test in order to guard against adding -// new references and forgetting to update GetStatsReferencedIds(). +// referenced ID based on dictionary type information and knowing what +// attributes are used as references, as opposed to iterating all attributes to +// find the ones with the "Id" or "Ids" suffix. As such, GetStatsReferencedIds() +// is tested as an integration test instead of a unit test in order to guard +// against adding new references and forgetting to update +// GetStatsReferencedIds(). TEST_F(RTCStatsIntegrationTest, GetStatsReferencedIds) { StartCall(); rtc::scoped_refptr report = GetStatsFromCallee(); for (const RTCStats& stats : *report) { - // Find all references by looking at all string members with the "Id" or + // Find all references by looking at all string attributes with the "Id" or // "Ids" suffix. std::set expected_ids; - for (const auto* member : stats.Members()) { - if (!member->is_defined()) + for (const auto& attribute : stats.Attributes()) { + if (!attribute.has_value()) continue; - if (member->type() == RTCStatsMemberInterface::kString) { - if (absl::EndsWith(member->name(), "Id")) { - const auto& id = member->cast_to>(); - expected_ids.insert(&(*id)); + if (attribute.holds_alternative()) { + if (absl::EndsWith(attribute.name(), "Id")) { + expected_ids.insert(&attribute.get()); } - } else if (member->type() == RTCStatsMemberInterface::kSequenceString) { - if (absl::EndsWith(member->name(), "Ids")) { - const auto& ids = - member->cast_to>>(); - for (const std::string& id : *ids) + } else if (attribute.holds_alternative>()) { + if (absl::EndsWith(attribute.name(), "Ids")) { + for (const std::string& id : + attribute.get>()) expected_ids.insert(&id); } } @@ -1184,16 +1213,17 @@ TEST_F(RTCStatsIntegrationTest, GetStatsReferencedIds) { } } -TEST_F(RTCStatsIntegrationTest, GetStatsContainsNoDuplicateMembers) { +TEST_F(RTCStatsIntegrationTest, GetStatsContainsNoDuplicateAttributes) { StartCall(); rtc::scoped_refptr report = GetStatsFromCallee(); for (const RTCStats& stats : *report) { - std::set member_names; - for (const auto* member : stats.Members()) { - EXPECT_TRUE(member_names.find(member->name()) == member_names.end()) - << member->name() << " is a duplicate!"; - member_names.insert(member->name()); + std::set attribute_names; + for (const auto& attribute : stats.Attributes()) { + EXPECT_TRUE(attribute_names.find(attribute.name()) == + attribute_names.end()) + << attribute.name() << " is a duplicate!"; + attribute_names.insert(attribute.name()); } } } diff --git a/third_party/libwebrtc/pc/rtc_stats_traversal.cc b/third_party/libwebrtc/pc/rtc_stats_traversal.cc index 04de55028c..dfd0570b8f 100644 --- a/third_party/libwebrtc/pc/rtc_stats_traversal.cc +++ b/third_party/libwebrtc/pc/rtc_stats_traversal.cc @@ -44,7 +44,7 @@ void TraverseAndTakeVisitedStats(RTCStatsReport* report, void AddIdIfDefined(const RTCStatsMember& id, std::vector* neighbor_ids) { - if (id.is_defined()) + if (id.has_value()) neighbor_ids->push_back(&(*id)); } diff --git a/third_party/libwebrtc/pc/rtp_transceiver.cc b/third_party/libwebrtc/pc/rtp_transceiver.cc index ca626cc94b..34d744a3bb 100644 --- a/third_party/libwebrtc/pc/rtp_transceiver.cc +++ b/third_party/libwebrtc/pc/rtp_transceiver.cc @@ -51,9 +51,7 @@ RTCError VerifyCodecPreferences( // transceiver.direction. if (!absl::c_any_of(codecs, [&recv_codecs](const RtpCodecCapability& codec) { - return codec.name != cricket::kRtxCodecName && - codec.name != cricket::kRedCodecName && - codec.name != cricket::kFlexfecCodecName && + return codec.IsMediaCodec() && absl::c_any_of(recv_codecs, [&codec](const cricket::Codec& recv_codec) { return recv_codec.MatchesRtpCodec(codec); @@ -65,9 +63,7 @@ RTCError VerifyCodecPreferences( } if (!absl::c_any_of(codecs, [&send_codecs](const RtpCodecCapability& codec) { - return codec.name != cricket::kRtxCodecName && - codec.name != cricket::kRedCodecName && - codec.name != cricket::kFlexfecCodecName && + return codec.IsMediaCodec() && absl::c_any_of(send_codecs, [&codec](const cricket::Codec& send_codec) { return send_codec.MatchesRtpCodec(codec); @@ -101,11 +97,9 @@ RTCError VerifyCodecPreferences( } } - // Check we have a real codec (not just rtx, red or fec) + // Check we have a real codec (not just rtx, red, fec or CN) if (absl::c_all_of(codecs, [](const RtpCodecCapability& codec) { - return codec.name == cricket::kRtxCodecName || - codec.name == cricket::kRedCodecName || - codec.name == cricket::kUlpfecCodecName; + return !codec.IsMediaCodec(); })) { LOG_AND_RETURN_ERROR( RTCErrorType::INVALID_MODIFICATION, diff --git a/third_party/libwebrtc/pc/sctp_utils_unittest.cc b/third_party/libwebrtc/pc/sctp_utils_unittest.cc index 9ef2068a05..64ad257983 100644 --- a/third_party/libwebrtc/pc/sctp_utils_unittest.cc +++ b/third_party/libwebrtc/pc/sctp_utils_unittest.cc @@ -72,11 +72,11 @@ class SctpUtilsTest : public ::testing::Test { EXPECT_EQ(label.size(), label_length); EXPECT_EQ(config.protocol.size(), protocol_length); - std::string label_output; - ASSERT_TRUE(buffer.ReadString(&label_output, label_length)); + absl::string_view label_output; + ASSERT_TRUE(buffer.ReadStringView(&label_output, label_length)); EXPECT_EQ(label, label_output); - std::string protocol_output; - ASSERT_TRUE(buffer.ReadString(&protocol_output, protocol_length)); + absl::string_view protocol_output; + ASSERT_TRUE(buffer.ReadStringView(&protocol_output, protocol_length)); EXPECT_EQ(config.protocol, protocol_output); } }; diff --git a/third_party/libwebrtc/pc/sdp_offer_answer.cc b/third_party/libwebrtc/pc/sdp_offer_answer.cc index 1e43833a0b..67c8d10241 100644 --- a/third_party/libwebrtc/pc/sdp_offer_answer.cc +++ b/third_party/libwebrtc/pc/sdp_offer_answer.cc @@ -77,11 +77,6 @@ using cricket::SimulcastLayerList; using cricket::StreamParams; using cricket::TransportInfo; -using cricket::LOCAL_PORT_TYPE; -using cricket::PRFLX_PORT_TYPE; -using cricket::RELAY_PORT_TYPE; -using cricket::STUN_PORT_TYPE; - namespace webrtc { namespace { @@ -2081,24 +2076,16 @@ void SdpOfferAnswerHandler::ApplyRemoteDescription( if (operation->unified_plan()) { ApplyRemoteDescriptionUpdateTransceiverState(operation->type()); } - - const cricket::AudioContentDescription* audio_desc = - GetFirstAudioContentDescription(remote_description()->description()); - const cricket::VideoContentDescription* video_desc = - GetFirstVideoContentDescription(remote_description()->description()); - - // Check if the descriptions include streams, just in case the peer supports - // MSID, but doesn't indicate so with "a=msid-semantic". - if (remote_description()->description()->msid_supported() || - (audio_desc && !audio_desc->streams().empty()) || - (video_desc && !video_desc->streams().empty())) { - remote_peer_supports_msid_ = true; - } + remote_peer_supports_msid_ = + remote_description()->description()->msid_signaling() != + cricket::kMsidSignalingNotUsed; if (!operation->unified_plan()) { PlanBUpdateSendersAndReceivers( - GetFirstAudioContent(remote_description()->description()), audio_desc, - GetFirstVideoContent(remote_description()->description()), video_desc); + GetFirstAudioContent(remote_description()->description()), + GetFirstAudioContentDescription(remote_description()->description()), + GetFirstVideoContent(remote_description()->description()), + GetFirstVideoContentDescription(remote_description()->description())); } if (operation->type() == SdpType::kAnswer) { diff --git a/third_party/libwebrtc/pc/sdp_offer_answer_unittest.cc b/third_party/libwebrtc/pc/sdp_offer_answer_unittest.cc index f158febac7..f4c35bfd20 100644 --- a/third_party/libwebrtc/pc/sdp_offer_answer_unittest.cc +++ b/third_party/libwebrtc/pc/sdp_offer_answer_unittest.cc @@ -1005,6 +1005,53 @@ TEST_F(SdpOfferAnswerTest, SdpMungingWithInvalidPayloadTypeIsRejected) { } } +TEST_F(SdpOfferAnswerTest, MsidSignalingInSubsequentOfferAnswer) { + auto pc = CreatePeerConnection(); + pc->AddAudioTrack("audio_track", {}); + + std::string sdp = + "v=0\r\n" + "o=- 0 3 IN IP4 127.0.0.1\r\n" + "s=-\r\n" + "t=0 0\r\n" + "a=msid-semantic: WMS\r\n" + "a=fingerprint:sha-1 " + "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n" + "a=setup:actpass\r\n" + "a=ice-ufrag:ETEn\r\n" + "a=ice-pwd:OtSK0WpNtpUjkY4+86js7Z/l\r\n" + "m=audio 9 UDP/TLS/RTP/SAVPF 111\r\n" + "c=IN IP4 0.0.0.0\r\n" + "a=rtcp:9 IN IP4 0.0.0.0\r\n" + "a=recvonly\r\n" + "a=rtcp-mux\r\n" + "a=rtpmap:111 opus/48000/2\r\n"; + + auto offer = CreateSessionDescription(SdpType::kOffer, sdp); + EXPECT_TRUE(pc->SetRemoteDescription(std::move(offer))); + + // Check the generated SDP. + auto answer = pc->CreateAnswer(); + answer->ToString(&sdp); + EXPECT_NE(std::string::npos, sdp.find("a=msid:- audio_track\r\n")); + + EXPECT_TRUE(pc->SetLocalDescription(std::move(answer))); + + // Check the local description object. + auto local_description = pc->pc()->local_description(); + ASSERT_EQ(local_description->description()->contents().size(), 1u); + auto streams = local_description->description() + ->contents()[0] + .media_description() + ->streams(); + ASSERT_EQ(streams.size(), 1u); + EXPECT_EQ(streams[0].id, "audio_track"); + + // Check the serialization of the local description. + local_description->ToString(&sdp); + EXPECT_NE(std::string::npos, sdp.find("a=msid:- audio_track\r\n")); +} + // Test variant with boolean order for audio-video and video-audio. class SdpOfferAnswerShuffleMediaTypes : public SdpOfferAnswerTest, @@ -1096,4 +1143,76 @@ INSTANTIATE_TEST_SUITE_P(SdpOfferAnswerShuffleMediaTypes, SdpOfferAnswerShuffleMediaTypes, ::testing::Values(true, false)); +TEST_F(SdpOfferAnswerTest, OfferWithNoCompatibleCodecsIsRejectedInAnswer) { + auto pc = CreatePeerConnection(); + // An offer with no common codecs. This should reject both contents + // in the answer without throwing an error. + std::string sdp = + "v=0\r\n" + "o=- 0 3 IN IP4 127.0.0.1\r\n" + "s=-\r\n" + "t=0 0\r\n" + "a=fingerprint:sha-1 " + "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n" + "a=setup:actpass\r\n" + "a=ice-ufrag:ETEn\r\n" + "a=ice-pwd:OtSK0WpNtpUjkY4+86js7Z/l\r\n" + "m=audio 9 RTP/SAVPF 97\r\n" + "c=IN IP4 0.0.0.0\r\n" + "a=sendrecv\r\n" + "a=rtpmap:97 x-unknown/90000\r\n" + "a=rtcp-mux\r\n" + "m=video 9 RTP/SAVPF 98\r\n" + "c=IN IP4 0.0.0.0\r\n" + "a=sendrecv\r\n" + "a=rtpmap:98 H263-1998/90000\r\n" + "a=fmtp:98 CIF=1;QCIF=1\r\n" + "a=rtcp-mux\r\n"; + + auto desc = CreateSessionDescription(SdpType::kOffer, sdp); + ASSERT_NE(desc, nullptr); + RTCError error; + pc->SetRemoteDescription(std::move(desc), &error); + EXPECT_TRUE(error.ok()); + + auto answer = pc->CreateAnswer(); + auto answer_contents = answer->description()->contents(); + ASSERT_EQ(answer_contents.size(), 2u); + EXPECT_EQ(answer_contents[0].rejected, true); + EXPECT_EQ(answer_contents[1].rejected, true); +} + +TEST_F(SdpOfferAnswerTest, + OfferWithNoMsidSemanticYieldsAnswerWithoutMsidSemantic) { + auto pc = CreatePeerConnection(); + // An offer with no msid-semantic line. The answer should not add one. + std::string sdp = + "v=0\r\n" + "o=- 0 3 IN IP4 127.0.0.1\r\n" + "s=-\r\n" + "t=0 0\r\n" + "a=fingerprint:sha-1 " + "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n" + "a=setup:actpass\r\n" + "a=ice-ufrag:ETEn\r\n" + "a=ice-pwd:OtSK0WpNtpUjkY4+86js7Z/l\r\n" + "m=audio 9 RTP/SAVPF 111\r\n" + "c=IN IP4 0.0.0.0\r\n" + "a=sendrecv\r\n" + "a=rtpmap:111 opus/48000/2\r\n" + "a=rtcp-mux\r\n"; + + auto desc = CreateSessionDescription(SdpType::kOffer, sdp); + ASSERT_NE(desc, nullptr); + EXPECT_EQ(desc->description()->msid_signaling(), + cricket::kMsidSignalingNotUsed); + RTCError error; + pc->SetRemoteDescription(std::move(desc), &error); + EXPECT_TRUE(error.ok()); + + auto answer = pc->CreateAnswer(); + EXPECT_EQ(answer->description()->msid_signaling(), + cricket::kMsidSignalingNotUsed); +} + } // namespace webrtc diff --git a/third_party/libwebrtc/pc/session_description.h b/third_party/libwebrtc/pc/session_description.h index 403e46529f..6ef9c316e1 100644 --- a/third_party/libwebrtc/pc/session_description.h +++ b/third_party/libwebrtc/pc/session_description.h @@ -468,13 +468,23 @@ const ContentInfo* FindContentInfoByName(const ContentInfos& contents, const ContentInfo* FindContentInfoByType(const ContentInfos& contents, const std::string& type); -// Determines how the MSID will be signaled in the SDP. These can be used as -// flags to indicate both or none. +// Determines how the MSID will be signaled in the SDP. +// These can be used as bit flags to indicate both or the special value none. enum MsidSignaling { - // Signal MSID with one a=msid line in the media section. + // MSID is not signaled. This is not a bit flag and must be compared for + // equality. + kMsidSignalingNotUsed = 0x0, + // Signal MSID with at least one a=msid line in the media section. + // This requires unified plan. kMsidSignalingMediaSection = 0x1, // Signal MSID with a=ssrc: msid lines in the media section. - kMsidSignalingSsrcAttribute = 0x2 + // This should only be used with plan-b but is signalled in + // offers for backward compability reasons. + kMsidSignalingSsrcAttribute = 0x2, + // Signal MSID with a=msid-semantic: WMS in the session section. + // This is deprecated but signalled for backward compability reasons. + // It is typically combined with 0x1 or 0x2. + kMsidSignalingSemantic = 0x4 }; // Describes a collection of contents, each with its own name and @@ -548,9 +558,6 @@ class SessionDescription { void RemoveGroupByName(const std::string& name); // Global attributes. - void set_msid_supported(bool supported) { msid_supported_ = supported; } - bool msid_supported() const { return msid_supported_; } - // Determines how the MSIDs were/will be signaled. Flag value composed of // MsidSignaling bits (see enum above). void set_msid_signaling(int msid_signaling) { @@ -582,10 +589,7 @@ class SessionDescription { ContentInfos contents_; TransportInfos transport_infos_; ContentGroups content_groups_; - bool msid_supported_ = true; - // Default to what Plan B would do. - // TODO(bugs.webrtc.org/8530): Change default to kMsidSignalingMediaSection. - int msid_signaling_ = kMsidSignalingSsrcAttribute; + int msid_signaling_ = kMsidSignalingMediaSection | kMsidSignalingSemantic; bool extmap_allow_mixed_ = true; }; diff --git a/third_party/libwebrtc/pc/test/integration_test_helpers.cc b/third_party/libwebrtc/pc/test/integration_test_helpers.cc index 64d8debc09..1f603ad561 100644 --- a/third_party/libwebrtc/pc/test/integration_test_helpers.cc +++ b/third_party/libwebrtc/pc/test/integration_test_helpers.cc @@ -22,7 +22,6 @@ void RemoveSsrcsAndMsids(cricket::SessionDescription* desc) { for (ContentInfo& content : desc->contents()) { content.media_description()->mutable_streams().clear(); } - desc->set_msid_supported(false); desc->set_msid_signaling(0); } diff --git a/third_party/libwebrtc/pc/test/integration_test_helpers.h b/third_party/libwebrtc/pc/test/integration_test_helpers.h index fb719e7ddd..7b3f11905d 100644 --- a/third_party/libwebrtc/pc/test/integration_test_helpers.h +++ b/third_party/libwebrtc/pc/test/integration_test_helpers.h @@ -649,8 +649,8 @@ class PeerConnectionIntegrationWrapper : public PeerConnectionObserver, auto received_stats = NewGetStats(); auto rtp_stats = received_stats->GetStatsOfType()[0]; - ASSERT_TRUE(rtp_stats->relative_packet_arrival_delay.is_defined()); - ASSERT_TRUE(rtp_stats->packets_received.is_defined()); + ASSERT_TRUE(rtp_stats->relative_packet_arrival_delay.has_value()); + ASSERT_TRUE(rtp_stats->packets_received.has_value()); rtp_stats_id_ = rtp_stats->id(); audio_packets_stat_ = *rtp_stats->packets_received; audio_delay_stat_ = *rtp_stats->relative_packet_arrival_delay; @@ -773,7 +773,7 @@ class PeerConnectionIntegrationWrapper : public PeerConnectionObserver, pc_factory_dependencies.task_queue_factory = CreateDefaultTaskQueueFactory(); pc_factory_dependencies.trials = std::make_unique(); - pc_factory_dependencies.metronome = + pc_factory_dependencies.decode_metronome = std::make_unique(TimeDelta::Millis(8)); pc_factory_dependencies.adm = fake_audio_capture_module_; @@ -800,8 +800,7 @@ class PeerConnectionIntegrationWrapper : public PeerConnectionObserver, pc_factory_dependencies.event_log_factory = std::move(event_log_factory); } else { pc_factory_dependencies.event_log_factory = - std::make_unique( - pc_factory_dependencies.task_queue_factory.get()); + std::make_unique(); } peer_connection_factory_ = CreateModularPeerConnectionFactory(std::move(pc_factory_dependencies)); @@ -1116,7 +1115,7 @@ class PeerConnectionIntegrationWrapper : public PeerConnectionObserver, if (remote_async_dns_resolver_) { const auto& local_candidate = candidate->candidate(); if (local_candidate.address().IsUnresolvedIP()) { - RTC_DCHECK(local_candidate.type() == cricket::LOCAL_PORT_TYPE); + RTC_DCHECK(local_candidate.is_local()); const auto resolved_ip = mdns_responder_->GetMappedAddressForName( local_candidate.address().hostname()); RTC_DCHECK(!resolved_ip.IsNil()); diff --git a/third_party/libwebrtc/pc/test/svc_e2e_tests.cc b/third_party/libwebrtc/pc/test/svc_e2e_tests.cc index 3fde5a44e0..b2382d700f 100644 --- a/third_party/libwebrtc/pc/test/svc_e2e_tests.cc +++ b/third_party/libwebrtc/pc/test/svc_e2e_tests.cc @@ -210,7 +210,7 @@ class SvcVideoQualityAnalyzer : public DefaultVideoQualityAnalyzer { // Extract the scalability mode reported in the stats. auto outbound_stats = report->GetStatsOfType(); for (const auto& stat : outbound_stats) { - if (stat->scalability_mode.is_defined()) { + if (stat->scalability_mode.has_value()) { reported_scalability_mode_ = *stat->scalability_mode; } } @@ -336,10 +336,9 @@ TEST_P(SvcTest, ScalabilityModeSupported) { RtpEncodingParameters parameters; parameters.scalability_mode = SvcTestParameters().scalability_mode; video.encoding_params.push_back(parameters); - alice->AddVideoConfig( - std::move(video), - CreateScreenShareFrameGenerator( - video, ScreenShareConfig(TimeDelta::Seconds(5)))); + auto generator = CreateScreenShareFrameGenerator( + video, ScreenShareConfig(TimeDelta::Seconds(5))); + alice->AddVideoConfig(std::move(video), std::move(generator)); alice->SetVideoCodecs({video_codec_config}); }, [](PeerConfigurer* bob) {}, std::move(analyzer)); diff --git a/third_party/libwebrtc/pc/webrtc_sdp.cc b/third_party/libwebrtc/pc/webrtc_sdp.cc index da024eab81..88f1ce0d1b 100644 --- a/third_party/libwebrtc/pc/webrtc_sdp.cc +++ b/third_party/libwebrtc/pc/webrtc_sdp.cc @@ -722,7 +722,7 @@ void CreateTracksFromSsrcInfos(const SsrcInfoVec& ssrc_infos, // This is the case with Plan B SDP msid signaling. stream_ids.push_back(ssrc_info.stream_id); track_id = ssrc_info.track_id; - } else { + } else if (msid_signaling == cricket::kMsidSignalingNotUsed) { // Since no media streams isn't supported with older SDP signaling, we // use a default stream id. stream_ids.push_back(kDefaultMsid); @@ -762,29 +762,6 @@ void GetMediaStreamIds(const ContentInfo* content, } } -// RFC 5245 -// It is RECOMMENDED that default candidates be chosen based on the -// likelihood of those candidates to work with the peer that is being -// contacted. It is RECOMMENDED that relayed > reflexive > host. -static const int kPreferenceUnknown = 0; -static const int kPreferenceHost = 1; -static const int kPreferenceReflexive = 2; -static const int kPreferenceRelayed = 3; - -static int GetCandidatePreferenceFromType(absl::string_view type) { - int preference = kPreferenceUnknown; - if (type == cricket::LOCAL_PORT_TYPE) { - preference = kPreferenceHost; - } else if (type == cricket::STUN_PORT_TYPE) { - preference = kPreferenceReflexive; - } else if (type == cricket::RELAY_PORT_TYPE) { - preference = kPreferenceRelayed; - } else { - RTC_DCHECK_NOTREACHED(); - } - return preference; -} - // Get ip and port of the default destination from the `candidates` with the // given value of `component_id`. The default candidate should be the one most // likely to work, typically IPv4 relay. @@ -800,7 +777,7 @@ static void GetDefaultDestination(const std::vector& candidates, *addr_type = kConnectionIpv4Addrtype; *port = kDummyPort; *ip = kDummyAddress; - int current_preference = kPreferenceUnknown; + int current_preference = 0; // Start with lowest preference int current_family = AF_UNSPEC; for (const Candidate& candidate : candidates) { if (candidate.component() != component_id) { @@ -810,7 +787,7 @@ static void GetDefaultDestination(const std::vector& candidates, if (candidate.protocol() != cricket::UDP_PROTOCOL_NAME) { continue; } - const int preference = GetCandidatePreferenceFromType(candidate.type()); + const int preference = candidate.type_preference(); const int family = candidate.address().ipaddr().family(); // See if this candidate is more preferable then the current one if it's the // same family. Or if the current family is IPv4 already so we could safely @@ -920,23 +897,31 @@ std::string SdpSerialize(const JsepSessionDescription& jdesc) { AddLine(os.str(), &message); } - // MediaStream semantics - InitAttrLine(kAttributeMsidSemantics, &os); - os << kSdpDelimiterColon << " " << kMediaStreamSemantic; + // MediaStream semantics. + // TODO(bugs.webrtc.org/10421): Change to & cricket::kMsidSignalingSemantic + // when we think it's safe to do so, so that we gradually fade out this old + // line that was removed from the specification. + if (desc->msid_signaling() != cricket::kMsidSignalingNotUsed) { + InitAttrLine(kAttributeMsidSemantics, &os); + os << kSdpDelimiterColon << " " << kMediaStreamSemantic; - std::set media_stream_ids; - const ContentInfo* audio_content = GetFirstAudioContent(desc); - if (audio_content) - GetMediaStreamIds(audio_content, &media_stream_ids); + // TODO(bugs.webrtc.org/10421): this code only looks at the first + // audio/video content. Fixing that might result in much larger SDP and the + // msid-semantic line should eventually go away so this is not worth fixing. + std::set media_stream_ids; + const ContentInfo* audio_content = GetFirstAudioContent(desc); + if (audio_content) + GetMediaStreamIds(audio_content, &media_stream_ids); - const ContentInfo* video_content = GetFirstVideoContent(desc); - if (video_content) - GetMediaStreamIds(video_content, &media_stream_ids); + const ContentInfo* video_content = GetFirstVideoContent(desc); + if (video_content) + GetMediaStreamIds(video_content, &media_stream_ids); - for (const std::string& id : media_stream_ids) { - os << " " << id; + for (const std::string& id : media_stream_ids) { + os << " " << id; + } + AddLine(os.str(), &message); } - AddLine(os.str(), &message); // a=ice-lite // @@ -1839,7 +1824,7 @@ bool IsFmtpParam(absl::string_view name) { return name != kCodecParamPTime && name != kCodecParamMaxPTime; } -bool WriteFmtpParameters(const cricket::CodecParameterMap& parameters, +bool WriteFmtpParameters(const webrtc::CodecParameterMap& parameters, rtc::StringBuilder* os) { bool empty = true; const char* delimiter = ""; // No delimiter before first parameter. @@ -1902,7 +1887,7 @@ bool GetMinValue(const std::vector& values, int* value) { } bool GetParameter(const std::string& name, - const cricket::CodecParameterMap& params, + const webrtc::CodecParameterMap& params, int* value) { std::map::const_iterator found = params.find(name); if (found == params.end()) { @@ -1997,13 +1982,13 @@ void BuildCandidate(const std::vector& candidates, // *(SP extension-att-name SP extension-att-value) std::string type; // Map the cricket candidate type to "host" / "srflx" / "prflx" / "relay" - if (candidate.type() == cricket::LOCAL_PORT_TYPE) { + if (candidate.is_local()) { type = kCandidateHost; - } else if (candidate.type() == cricket::STUN_PORT_TYPE) { + } else if (candidate.is_stun()) { type = kCandidateSrflx; - } else if (candidate.type() == cricket::RELAY_PORT_TYPE) { + } else if (candidate.is_relay()) { type = kCandidateRelay; - } else if (candidate.type() == cricket::PRFLX_PORT_TYPE) { + } else if (candidate.is_prflx()) { type = kCandidatePrflx; // Peer reflexive candidate may be signaled for being removed. } else { @@ -2131,7 +2116,7 @@ bool ParseSessionDescription(absl::string_view message, SdpParseError* error) { absl::optional line; - desc->set_msid_supported(false); + desc->set_msid_signaling(cricket::kMsidSignalingNotUsed); desc->set_extmap_allow_mixed(false); // RFC 4566 // v= (protocol version) @@ -2273,8 +2258,9 @@ bool ParseSessionDescription(absl::string_view message, if (!GetValue(*aline, kAttributeMsidSemantics, &semantics, error)) { return false; } - desc->set_msid_supported( - CaseInsensitiveFind(semantics, kMediaStreamSemantic)); + if (CaseInsensitiveFind(semantics, kMediaStreamSemantic)) { + desc->set_msid_signaling(cricket::kMsidSignalingSemantic); + } } else if (HasAttribute(*aline, kAttributeExtmapAllowMixed)) { desc->set_extmap_allow_mixed(true); } else if (HasAttribute(*aline, kAttributeExtmap)) { @@ -2614,6 +2600,25 @@ void MaybeCreateStaticPayloadAudioCodecs(const std::vector& fmts, } } +static void BackfillCodecParameters(std::vector& codecs) { + for (auto& codec : codecs) { + std::string unused_value; + if (absl::EqualsIgnoreCase(cricket::kVp9CodecName, codec.name)) { + // https://datatracker.ietf.org/doc/html/draft-ietf-payload-vp9#section-6 + // profile-id defaults to "0" + if (!codec.GetParam(cricket::kVP9ProfileId, &unused_value)) { + codec.SetParam(cricket::kVP9ProfileId, "0"); + } + } else if (absl::EqualsIgnoreCase(cricket::kH264CodecName, codec.name)) { + // https://www.rfc-editor.org/rfc/rfc6184#section-6.2 + // packetization-mode defaults to "0" + if (!codec.GetParam(cricket::kH264FmtpPacketizationMode, &unused_value)) { + codec.SetParam(cricket::kH264FmtpPacketizationMode, "0"); + } + } + } +} + static std::unique_ptr ParseContentDescription( absl::string_view message, const cricket::MediaType media_type, @@ -2657,6 +2662,9 @@ static std::unique_ptr ParseContentDescription( const cricket::Codec& b) { return payload_type_preferences[a.id] > payload_type_preferences[b.id]; }); + // Backfill any default parameters. + BackfillCodecParameters(codecs); + media_desc->set_codecs(codecs); return media_desc; } @@ -2672,7 +2680,7 @@ bool ParseMediaDescription( SdpParseError* error) { RTC_DCHECK(desc != NULL); int mline_index = -1; - int msid_signaling = 0; + int msid_signaling = desc->msid_signaling(); // Zero or more media descriptions // RFC 4566 @@ -2724,7 +2732,7 @@ bool ParseMediaDescription( std::unique_ptr content; std::string content_name; bool bundle_only = false; - int section_msid_signaling = 0; + int section_msid_signaling = cricket::kMsidSignalingNotUsed; absl::string_view media_type = fields[0]; if ((media_type == kMediaTypeVideo || media_type == kMediaTypeAudio) && !cricket::IsRtpProtocol(protocol)) { @@ -2854,7 +2862,7 @@ bool ParseMediaDescription( return true; } -void AddParameters(const cricket::CodecParameterMap& parameters, +void AddParameters(const webrtc::CodecParameterMap& parameters, cricket::Codec* codec) { for (const auto& entry : parameters) { const std::string& key = entry.first; @@ -2917,7 +2925,7 @@ void AddOrReplaceCodec(MediaContentDescription* content_desc, // to `parameters`. void UpdateCodec(MediaContentDescription* content_desc, int payload_type, - const cricket::CodecParameterMap& parameters) { + const webrtc::CodecParameterMap& parameters) { // Codec might already have been populated (from rtpmap). cricket::Codec new_codec = GetCodecWithPayloadType( content_desc->type(), content_desc->codecs(), payload_type); @@ -3740,7 +3748,7 @@ bool ParseFmtpAttributes(absl::string_view line, } // Parse out format specific parameters. - cricket::CodecParameterMap codec_params; + webrtc::CodecParameterMap codec_params; for (absl::string_view param : rtc::split(line_params, kSdpDelimiterSemicolonChar)) { std::string name; diff --git a/third_party/libwebrtc/pc/webrtc_sdp.h b/third_party/libwebrtc/pc/webrtc_sdp.h index f7759bd139..052ed546c8 100644 --- a/third_party/libwebrtc/pc/webrtc_sdp.h +++ b/third_party/libwebrtc/pc/webrtc_sdp.h @@ -109,7 +109,7 @@ RTC_EXPORT bool ParseCandidate(absl::string_view message, // parameters are not considered to be part of the FMTP line, see the function // IsFmtpParam(). Returns true if the set of FMTP parameters is nonempty, false // otherwise. -bool WriteFmtpParameters(const cricket::CodecParameterMap& parameters, +bool WriteFmtpParameters(const webrtc::CodecParameterMap& parameters, rtc::StringBuilder* os); } // namespace webrtc diff --git a/third_party/libwebrtc/pc/webrtc_sdp_unittest.cc b/third_party/libwebrtc/pc/webrtc_sdp_unittest.cc index ae26ba0ce2..eb9bc729c6 100644 --- a/third_party/libwebrtc/pc/webrtc_sdp_unittest.cc +++ b/third_party/libwebrtc/pc/webrtc_sdp_unittest.cc @@ -173,6 +173,7 @@ static const char kSdpFullString[] = "a=ice-ufrag:ufrag_voice\r\na=ice-pwd:pwd_voice\r\n" "a=mid:audio_content_name\r\n" "a=sendrecv\r\n" + "a=msid:local_stream_1 audio_track_id_1\r\n" "a=rtcp-mux\r\n" "a=rtcp-rsize\r\n" "a=crypto:1 AES_CM_128_HMAC_SHA1_32 " @@ -182,7 +183,6 @@ static const char kSdpFullString[] = "a=rtpmap:103 ISAC/16000\r\n" "a=rtpmap:104 ISAC/32000\r\n" "a=ssrc:1 cname:stream_1_cname\r\n" - "a=ssrc:1 msid:local_stream_1 audio_track_id_1\r\n" "m=video 3457 RTP/SAVPF 120\r\n" "c=IN IP4 74.125.224.39\r\n" "a=rtcp:3456 IN IP4 74.125.224.39\r\n" @@ -201,14 +201,13 @@ static const char kSdpFullString[] = "a=ice-ufrag:ufrag_video\r\na=ice-pwd:pwd_video\r\n" "a=mid:video_content_name\r\n" "a=sendrecv\r\n" + "a=msid:local_stream_1 video_track_id_1\r\n" "a=crypto:1 AES_CM_128_HMAC_SHA1_80 " "inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj|2^20|1:32\r\n" "a=rtpmap:120 VP8/90000\r\n" "a=ssrc-group:FEC 2 3\r\n" "a=ssrc:2 cname:stream_1_cname\r\n" - "a=ssrc:2 msid:local_stream_1 video_track_id_1\r\n" - "a=ssrc:3 cname:stream_1_cname\r\n" - "a=ssrc:3 msid:local_stream_1 video_track_id_1\r\n"; + "a=ssrc:3 cname:stream_1_cname\r\n"; // SDP reference string without the candidates. static const char kSdpString[] = @@ -224,6 +223,7 @@ static const char kSdpString[] = "a=ice-ufrag:ufrag_voice\r\na=ice-pwd:pwd_voice\r\n" "a=mid:audio_content_name\r\n" "a=sendrecv\r\n" + "a=msid:local_stream_1 audio_track_id_1\r\n" "a=rtcp-mux\r\n" "a=rtcp-rsize\r\n" "a=crypto:1 AES_CM_128_HMAC_SHA1_32 " @@ -233,21 +233,19 @@ static const char kSdpString[] = "a=rtpmap:103 ISAC/16000\r\n" "a=rtpmap:104 ISAC/32000\r\n" "a=ssrc:1 cname:stream_1_cname\r\n" - "a=ssrc:1 msid:local_stream_1 audio_track_id_1\r\n" "m=video 9 RTP/SAVPF 120\r\n" "c=IN IP4 0.0.0.0\r\n" "a=rtcp:9 IN IP4 0.0.0.0\r\n" "a=ice-ufrag:ufrag_video\r\na=ice-pwd:pwd_video\r\n" "a=mid:video_content_name\r\n" "a=sendrecv\r\n" + "a=msid:local_stream_1 video_track_id_1\r\n" "a=crypto:1 AES_CM_128_HMAC_SHA1_80 " "inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj|2^20|1:32\r\n" "a=rtpmap:120 VP8/90000\r\n" "a=ssrc-group:FEC 2 3\r\n" "a=ssrc:2 cname:stream_1_cname\r\n" - "a=ssrc:2 msid:local_stream_1 video_track_id_1\r\n" - "a=ssrc:3 cname:stream_1_cname\r\n" - "a=ssrc:3 msid:local_stream_1 video_track_id_1\r\n"; + "a=ssrc:3 cname:stream_1_cname\r\n"; // draft-ietf-mmusic-sctp-sdp-03 static const char kSdpSctpDataChannelString[] = @@ -363,6 +361,7 @@ static const char kBundleOnlySdpFullString[] = "generation 2\r\n" "a=ice-ufrag:ufrag_voice\r\na=ice-pwd:pwd_voice\r\n" "a=mid:audio_content_name\r\n" + "a=msid:local_stream_1 audio_track_id_1\r\n" "a=sendrecv\r\n" "a=rtcp-mux\r\n" "a=rtcp-rsize\r\n" @@ -373,21 +372,19 @@ static const char kBundleOnlySdpFullString[] = "a=rtpmap:103 ISAC/16000\r\n" "a=rtpmap:104 ISAC/32000\r\n" "a=ssrc:1 cname:stream_1_cname\r\n" - "a=ssrc:1 msid:local_stream_1 audio_track_id_1\r\n" "m=video 0 RTP/SAVPF 120\r\n" "c=IN IP4 0.0.0.0\r\n" "a=rtcp:9 IN IP4 0.0.0.0\r\n" "a=bundle-only\r\n" "a=mid:video_content_name\r\n" + "a=msid:local_stream_1 video_track_id_1\r\n" "a=sendrecv\r\n" "a=crypto:1 AES_CM_128_HMAC_SHA1_80 " "inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj|2^20|1:32\r\n" "a=rtpmap:120 VP8/90000\r\n" "a=ssrc-group:FEC 2 3\r\n" "a=ssrc:2 cname:stream_1_cname\r\n" - "a=ssrc:2 msid:local_stream_1 video_track_id_1\r\n" - "a=ssrc:3 cname:stream_1_cname\r\n" - "a=ssrc:3 msid:local_stream_1 video_track_id_1\r\n"; + "a=ssrc:3 cname:stream_1_cname\r\n"; // Plan B SDP reference string, with 2 streams, 2 audio tracks and 3 video // tracks. @@ -1168,7 +1165,8 @@ class WebRtcSdpTest : public ::testing::Test { absl::WrapUnique(audio_desc_)); desc_.AddContent(kVideoContentName, MediaProtocolType::kRtp, absl::WrapUnique(video_desc_)); - + desc_.set_msid_signaling(cricket::kMsidSignalingSsrcAttribute | + cricket::kMsidSignalingSemantic); ASSERT_TRUE(jdesc_.Initialize(desc_.Clone(), jdesc_.session_id(), jdesc_.session_version())); } @@ -1219,7 +1217,8 @@ class WebRtcSdpTest : public ::testing::Test { absl::WrapUnique(video_desc_3)); desc_.AddTransportInfo(TransportInfo( kVideoContentName3, TransportDescription(kUfragVideo3, kPwdVideo3))); - desc_.set_msid_signaling(cricket::kMsidSignalingMediaSection); + desc_.set_msid_signaling(cricket::kMsidSignalingMediaSection | + cricket::kMsidSignalingSemantic); ASSERT_TRUE(jdesc_.Initialize(desc_.Clone(), jdesc_.session_id(), jdesc_.session_version())); @@ -1299,7 +1298,8 @@ class WebRtcSdpTest : public ::testing::Test { absl::WrapUnique(audio_desc)); // Enable signaling a=msid lines. - desc_.set_msid_signaling(cricket::kMsidSignalingMediaSection); + desc_.set_msid_signaling(cricket::kMsidSignalingMediaSection | + cricket::kMsidSignalingSemantic); ASSERT_TRUE(jdesc_.Initialize(desc_.Clone(), jdesc_.session_id(), jdesc_.session_version())); } @@ -1508,7 +1508,7 @@ class WebRtcSdpTest : public ::testing::Test { } // global attributes - EXPECT_EQ(desc1.msid_supported(), desc2.msid_supported()); + EXPECT_EQ(desc1.msid_signaling(), desc2.msid_signaling()); EXPECT_EQ(desc1.extmap_allow_mixed(), desc2.extmap_allow_mixed()); } @@ -1815,10 +1815,10 @@ class WebRtcSdpTest : public ::testing::Test { } } - void VerifyCodecParameter(const cricket::CodecParameterMap& params, + void VerifyCodecParameter(const webrtc::CodecParameterMap& params, const std::string& name, int expected_value) { - cricket::CodecParameterMap::const_iterator found = params.find(name); + webrtc::CodecParameterMap::const_iterator found = params.find(name); ASSERT_TRUE(found != params.end()); EXPECT_EQ(found->second, rtc::ToString(expected_value)); } @@ -2449,7 +2449,7 @@ TEST_F(WebRtcSdpTest, DeserializeSessionDescriptionWithoutRtpmapButWithFmtp) { EXPECT_EQ("G729", g729.name); EXPECT_EQ(8000, g729.clockrate); EXPECT_EQ(18, g729.id); - cricket::CodecParameterMap::iterator found = g729.params.find("annexb"); + webrtc::CodecParameterMap::iterator found = g729.params.find("annexb"); ASSERT_TRUE(found != g729.params.end()); EXPECT_EQ(found->second, "yes"); @@ -3035,7 +3035,7 @@ TEST_F(WebRtcSdpTest, DeserializeSessionDescriptionWithoutEndLineBreak) { // Deserialize SdpParseError error; EXPECT_FALSE(webrtc::SdpDeserialize(sdp, &jdesc, &error)); - const std::string lastline = "a=ssrc:3 msid:local_stream_1 video_track_id_1"; + const std::string lastline = "a=ssrc:3 cname:stream_1_cname"; EXPECT_EQ(lastline, error.line); EXPECT_EQ("Invalid SDP line.", error.description); } @@ -3292,7 +3292,7 @@ TEST_F(WebRtcSdpTest, DeserializeVideoFmtp) { cricket::VideoCodec vp8 = vcd->codecs()[0]; EXPECT_EQ("VP8", vp8.name); EXPECT_EQ(120, vp8.id); - cricket::CodecParameterMap::iterator found = + webrtc::CodecParameterMap::iterator found = vp8.params.find("x-google-min-bitrate"); ASSERT_TRUE(found != vp8.params.end()); EXPECT_EQ(found->second, "10"); @@ -3326,7 +3326,7 @@ TEST_F(WebRtcSdpTest, DeserializeVideoFmtpWithSprops) { cricket::VideoCodec h264 = vcd->codecs()[0]; EXPECT_EQ("H264", h264.name); EXPECT_EQ(98, h264.id); - cricket::CodecParameterMap::const_iterator found = + webrtc::CodecParameterMap::const_iterator found = h264.params.find("profile-level-id"); ASSERT_TRUE(found != h264.params.end()); EXPECT_EQ(found->second, "42A01E"); @@ -3359,7 +3359,7 @@ TEST_F(WebRtcSdpTest, DeserializeVideoFmtpWithSpace) { cricket::VideoCodec vp8 = vcd->codecs()[0]; EXPECT_EQ("VP8", vp8.name); EXPECT_EQ(120, vp8.id); - cricket::CodecParameterMap::iterator found = + webrtc::CodecParameterMap::iterator found = vp8.params.find("x-google-min-bitrate"); ASSERT_TRUE(found != vp8.params.end()); EXPECT_EQ(found->second, "10"); @@ -3751,7 +3751,7 @@ TEST_F(WebRtcSdpTest, DeserializeSessionDescriptionSpecialMsid) { // Create both msid lines for Plan B and Unified Plan support. MakeUnifiedPlanDescriptionMultipleStreamIds( cricket::kMsidSignalingMediaSection | - cricket::kMsidSignalingSsrcAttribute); + cricket::kMsidSignalingSsrcAttribute | cricket::kMsidSignalingSemantic); JsepSessionDescription deserialized_description(kDummyType); EXPECT_TRUE(SdpDeserialize(kUnifiedPlanSdpFullStringWithSpecialMsid, @@ -3759,7 +3759,8 @@ TEST_F(WebRtcSdpTest, DeserializeSessionDescriptionSpecialMsid) { EXPECT_TRUE(CompareSessionDescription(jdesc_, deserialized_description)); EXPECT_EQ(cricket::kMsidSignalingMediaSection | - cricket::kMsidSignalingSsrcAttribute, + cricket::kMsidSignalingSsrcAttribute | + cricket::kMsidSignalingSemantic, deserialized_description.description()->msid_signaling()); } @@ -3771,7 +3772,7 @@ TEST_F(WebRtcSdpTest, SerializeSessionDescriptionSpecialMsid) { // Create both msid lines for Plan B and Unified Plan support. MakeUnifiedPlanDescriptionMultipleStreamIds( cricket::kMsidSignalingMediaSection | - cricket::kMsidSignalingSsrcAttribute); + cricket::kMsidSignalingSsrcAttribute | cricket::kMsidSignalingSemantic); std::string serialized_sdp = webrtc::SdpSerialize(jdesc_); // We explicitly test that the serialized SDP string is equal to the hard // coded SDP string. This is necessary, because in the parser "a=msid" lines @@ -3787,7 +3788,7 @@ TEST_F(WebRtcSdpTest, SerializeSessionDescriptionSpecialMsid) { TEST_F(WebRtcSdpTest, UnifiedPlanDeserializeSessionDescriptionSpecialMsid) { // Only create a=msid lines for strictly Unified Plan stream ID support. MakeUnifiedPlanDescriptionMultipleStreamIds( - cricket::kMsidSignalingMediaSection); + cricket::kMsidSignalingMediaSection | cricket::kMsidSignalingSemantic); JsepSessionDescription deserialized_description(kDummyType); std::string unified_plan_sdp_string = @@ -3805,7 +3806,7 @@ TEST_F(WebRtcSdpTest, UnifiedPlanDeserializeSessionDescriptionSpecialMsid) { TEST_F(WebRtcSdpTest, UnifiedPlanSerializeSessionDescriptionSpecialMsid) { // Only create a=msid lines for strictly Unified Plan stream ID support. MakeUnifiedPlanDescriptionMultipleStreamIds( - cricket::kMsidSignalingMediaSection); + cricket::kMsidSignalingMediaSection | cricket::kMsidSignalingSemantic); TestSerialize(jdesc_); } @@ -3837,7 +3838,8 @@ TEST_F(WebRtcSdpTest, SerializeUnifiedPlanSessionDescriptionNoSsrcSignaling) { TEST_F(WebRtcSdpTest, EmptyDescriptionHasNoMsidSignaling) { JsepSessionDescription jsep_desc(kDummyType); ASSERT_TRUE(SdpDeserialize(kSdpSessionString, &jsep_desc)); - EXPECT_EQ(0, jsep_desc.description()->msid_signaling()); + EXPECT_EQ(cricket::kMsidSignalingSemantic, + jsep_desc.description()->msid_signaling()); } TEST_F(WebRtcSdpTest, DataChannelOnlyHasNoMsidSignaling) { @@ -3845,21 +3847,24 @@ TEST_F(WebRtcSdpTest, DataChannelOnlyHasNoMsidSignaling) { std::string sdp = kSdpSessionString; sdp += kSdpSctpDataChannelString; ASSERT_TRUE(SdpDeserialize(sdp, &jsep_desc)); - EXPECT_EQ(0, jsep_desc.description()->msid_signaling()); + EXPECT_EQ(cricket::kMsidSignalingSemantic, + jsep_desc.description()->msid_signaling()); } TEST_F(WebRtcSdpTest, PlanBHasSsrcAttributeMsidSignaling) { JsepSessionDescription jsep_desc(kDummyType); ASSERT_TRUE(SdpDeserialize(kPlanBSdpFullString, &jsep_desc)); - EXPECT_EQ(cricket::kMsidSignalingSsrcAttribute, - jsep_desc.description()->msid_signaling()); + EXPECT_EQ( + cricket::kMsidSignalingSsrcAttribute | cricket::kMsidSignalingSemantic, + jsep_desc.description()->msid_signaling()); } TEST_F(WebRtcSdpTest, UnifiedPlanHasMediaSectionMsidSignaling) { JsepSessionDescription jsep_desc(kDummyType); ASSERT_TRUE(SdpDeserialize(kUnifiedPlanSdpFullString, &jsep_desc)); - EXPECT_EQ(cricket::kMsidSignalingMediaSection, - jsep_desc.description()->msid_signaling()); + EXPECT_EQ( + cricket::kMsidSignalingMediaSection | cricket::kMsidSignalingSemantic, + jsep_desc.description()->msid_signaling()); } const char kMediaSectionMsidLine[] = "a=msid:local_stream_1 audio_track_id_1"; @@ -3893,6 +3898,13 @@ TEST_F(WebRtcSdpTest, SerializeBothMediaSectionAndSsrcAttributeMsid) { EXPECT_NE(std::string::npos, sdp.find(kSsrcAttributeMsidLine)); } +TEST_F(WebRtcSdpTest, SerializeWithoutMsidSemantics) { + jdesc_.description()->set_msid_signaling(cricket::kMsidSignalingNotUsed); + std::string sdp = webrtc::SdpSerialize(jdesc_); + + EXPECT_EQ(std::string::npos, sdp.find("a=msid-semantic:")); +} + // Regression test for integer overflow bug: // https://bugs.chromium.org/p/chromium/issues/detail?id=648071 TEST_F(WebRtcSdpTest, DeserializeLargeBandwidthLimit) { @@ -4459,16 +4471,15 @@ TEST_F(WebRtcSdpTest, DeserializeEmptySessionName) { // Simulcast malformed input test for invalid format. TEST_F(WebRtcSdpTest, DeserializeSimulcastNegative_EmptyAttribute) { - ExpectParseFailureWithNewLines( - "a=ssrc:3 msid:local_stream_1 video_track_id_1\r\n", "a=simulcast:\r\n", - "a=simulcast:"); + ExpectParseFailureWithNewLines("a=ssrc:3 cname:stream_1_cname\r\n", + "a=simulcast:\r\n", "a=simulcast:"); } // Tests that duplicate simulcast entries in the SDP triggers a parse failure. TEST_F(WebRtcSdpTest, DeserializeSimulcastNegative_DuplicateAttribute) { - ExpectParseFailureWithNewLines( - "a=ssrc:3 msid:local_stream_1 video_track_id_1\r\n", - "a=simulcast:send 1\r\na=simulcast:recv 2\r\n", "a=simulcast:"); + ExpectParseFailureWithNewLines("a=ssrc:3 cname:stream_1_cname\r\n", + "a=simulcast:send 1\r\na=simulcast:recv 2\r\n", + "a=simulcast:"); } // Validates that deserialization uses the a=simulcast: attribute @@ -4802,6 +4813,7 @@ TEST_F(WebRtcSdpTest, DeserializeSessionDescriptionWithoutCname) { EXPECT_TRUE(SdpDeserialize(sdp_without_cname, &new_jdesc)); audio_desc_->mutable_streams()[0].cname = ""; + audio_desc_->mutable_streams()[0].ssrcs = {}; ASSERT_TRUE(jdesc_.Initialize(desc_.Clone(), jdesc_.session_id(), jdesc_.session_version())); EXPECT_TRUE(CompareSessionDescription(jdesc_, new_jdesc)); @@ -5096,3 +5108,42 @@ TEST_F(WebRtcSdpTest, IgnoresUnknownAttributeLines) { JsepSessionDescription jdesc(kDummyType); EXPECT_TRUE(SdpDeserialize(sdp, &jdesc)); } + +TEST_F(WebRtcSdpTest, BackfillsDefaultFmtpValues) { + std::string sdp = + "v=0\r\n" + "o=- 0 3 IN IP4 127.0.0.1\r\n" + "s=-\r\n" + "t=0 0\r\n" + "a=group:BUNDLE 0\r\n" + "a=fingerprint:sha-1 " + "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n" + "a=setup:actpass\r\n" + "a=ice-ufrag:ETEn\r\n" + "a=ice-pwd:OtSK0WpNtpUjkY4+86js7Z/l\r\n" + "m=video 9 UDP/TLS/RTP/SAVPF 96 97\r\n" + "c=IN IP4 0.0.0.0\r\n" + "a=rtcp-mux\r\n" + "a=sendonly\r\n" + "a=mid:0\r\n" + "a=rtpmap:96 H264/90000\r\n" + "a=rtpmap:97 VP9/90000\r\n" + "a=ssrc:1234 cname:test\r\n"; + JsepSessionDescription jdesc(kDummyType); + EXPECT_TRUE(SdpDeserialize(sdp, &jdesc)); + ASSERT_EQ(1u, jdesc.description()->contents().size()); + const auto content = jdesc.description()->contents()[0]; + const auto* description = content.media_description(); + ASSERT_NE(description, nullptr); + const std::vector codecs = description->codecs(); + ASSERT_EQ(codecs.size(), 2u); + std::string value; + + EXPECT_EQ(codecs[0].name, "H264"); + EXPECT_TRUE(codecs[0].GetParam("packetization-mode", &value)); + EXPECT_EQ(value, "0"); + + EXPECT_EQ(codecs[1].name, "VP9"); + EXPECT_TRUE(codecs[1].GetParam("profile-id", &value)); + EXPECT_EQ(value, "0"); +} -- cgit v1.2.3