diff --git a/api/audio_codecs/audio_encoder.cc b/api/audio_codecs/audio_encoder.cc index ae251333e2..2c1111814e 100644 --- a/api/audio_codecs/audio_encoder.cc +++ b/api/audio_codecs/audio_encoder.cc @@ -82,7 +82,9 @@ void AudioEncoder::OnReceivedUplinkPacketLossFraction( float uplink_packet_loss_fraction) {} void AudioEncoder::OnReceivedUplinkRecoverablePacketLossFraction( - float uplink_recoverable_packet_loss_fraction) {} + float uplink_recoverable_packet_loss_fraction) { + RTC_NOTREACHED(); +} void AudioEncoder::OnReceivedTargetAudioBitrate(int target_audio_bitrate_bps) { OnReceivedUplinkBandwidth(target_audio_bitrate_bps, absl::nullopt); diff --git a/api/audio_codecs/audio_encoder.h b/api/audio_codecs/audio_encoder.h index c6efa47ffc..c6e572c87b 100644 --- a/api/audio_codecs/audio_encoder.h +++ b/api/audio_codecs/audio_encoder.h @@ -210,10 +210,7 @@ class AudioEncoder { virtual void OnReceivedUplinkPacketLossFraction( float uplink_packet_loss_fraction); - // Provides 1st-order-FEC-recoverable uplink packet loss rate to this encoder - // to allow it to adapt. - // |uplink_recoverable_packet_loss_fraction| is in the range [0.0, 1.0]. - virtual void OnReceivedUplinkRecoverablePacketLossFraction( + RTC_DEPRECATED virtual void OnReceivedUplinkRecoverablePacketLossFraction( float uplink_recoverable_packet_loss_fraction); // Provides target audio bitrate to this encoder to allow it to adapt. diff --git a/audio/BUILD.gn b/audio/BUILD.gn index bfda54292f..927c948349 100644 --- a/audio/BUILD.gn +++ b/audio/BUILD.gn @@ -33,8 +33,6 @@ rtc_library("audio") { "null_audio_poller.h", "remix_resample.cc", "remix_resample.h", - "transport_feedback_packet_loss_tracker.cc", - "transport_feedback_packet_loss_tracker.h", ] deps = [ @@ -123,7 +121,6 @@ if (rtc_include_tests) { "remix_resample_unittest.cc", "test/audio_stats_test.cc", "test/media_transport_test.cc", - "transport_feedback_packet_loss_tracker_unittest.cc", ] deps = [ ":audio", diff --git a/audio/audio_send_stream.cc b/audio/audio_send_stream.cc index 7ef9852838..323b7a9ef2 100644 --- a/audio/audio_send_stream.cc +++ b/audio/audio_send_stream.cc @@ -42,10 +42,6 @@ namespace webrtc { namespace { -// TODO(eladalon): Subsequent CL will make these values experiment-dependent. -constexpr size_t kPacketLossTrackerMaxWindowSizeMs = 15000; -constexpr size_t kPacketLossRateMinNumAckedPackets = 50; -constexpr size_t kRecoverablePacketLossRateMinNumAckedPairs = 40; void UpdateEventLogStreamConfig(RtcEventLog* event_log, const AudioSendStream::Config& config, @@ -162,9 +158,6 @@ AudioSendStream::AudioSendStream( !field_trial::IsDisabled("WebRTC-Audio-LegacyOverhead")), bitrate_allocator_(bitrate_allocator), rtp_transport_(rtp_transport), - packet_loss_tracker_(kPacketLossTrackerMaxWindowSizeMs, - kPacketLossRateMinNumAckedPackets, - kRecoverablePacketLossRateMinNumAckedPairs), rtp_rtcp_module_(nullptr), suspended_rtp_state_(suspended_rtp_state) { RTC_LOG(LS_INFO) << "AudioSendStream: " << config.rtp.ssrc; @@ -195,15 +188,12 @@ AudioSendStream::AudioSendStream( ConfigureStream(config, true); pacer_thread_checker_.Detach(); - // Signal congestion controller this object is ready for OnPacket* callbacks. - rtp_transport_->RegisterPacketFeedbackObserver(this); } AudioSendStream::~AudioSendStream() { RTC_DCHECK(worker_thread_checker_.IsCurrent()); RTC_LOG(LS_INFO) << "~AudioSendStream: " << config_.rtp.ssrc; RTC_DCHECK(!sending_); - rtp_transport_->DeRegisterPacketFeedbackObserver(this); channel_send_->ResetSenderCongestionControlObjects(); // Blocking call to synchronize state with worker queue to ensure that there // are no pending tasks left that keeps references to audio. @@ -258,8 +248,6 @@ void AudioSendStream::ConfigureStream( const auto& old_config = config_; - config_cs_.Enter(); - // Configuration parameters which cannot be changed. RTC_DCHECK(first_time || old_config.send_transport == new_config.send_transport); @@ -284,8 +272,6 @@ void AudioSendStream::ConfigureStream( const ExtensionIds old_ids = FindExtensionIds(old_config.rtp.extensions); const ExtensionIds new_ids = FindExtensionIds(new_config.rtp.extensions); - config_cs_.Leave(); - // Audio level indication if (first_time || new_ids.audio_level != old_ids.audio_level) { channel_send_->SetSendAudioLevelIndicationStatus(new_ids.audio_level != 0, @@ -328,7 +314,6 @@ void AudioSendStream::ConfigureStream( channel_send_->RegisterSenderCongestionControlObjects(rtp_transport_, bandwidth_observer); } - config_cs_.Enter(); // MID RTP header extension. if ((first_time || new_ids.mid != old_ids.mid || new_config.rtp.mid != old_config.rtp.mid) && @@ -352,7 +337,6 @@ void AudioSendStream::ConfigureStream( ReconfigureBitrateObserver(new_config); } config_ = new_config; - config_cs_.Leave(); } void AudioSendStream::Start() { @@ -513,45 +497,6 @@ uint32_t AudioSendStream::OnBitrateUpdated(BitrateAllocationUpdate update) { return 0; } -void AudioSendStream::OnPacketAdded(uint32_t ssrc, uint16_t seq_num) { - RTC_DCHECK(pacer_thread_checker_.IsCurrent()); - // Only packets that belong to this stream are of interest. - bool same_ssrc; - { - rtc::CritScope lock(&config_cs_); - same_ssrc = ssrc == config_.rtp.ssrc; - } - if (same_ssrc) { - rtc::CritScope lock(&packet_loss_tracker_cs_); - // TODO(eladalon): This function call could potentially reset the window, - // setting both PLR and RPLR to unknown. Consider (during upcoming - // refactoring) passing an indication of such an event. - packet_loss_tracker_.OnPacketAdded(seq_num, clock_->TimeInMilliseconds()); - } -} - -void AudioSendStream::OnPacketFeedbackVector( - const std::vector& packet_feedback_vector) { - RTC_DCHECK(worker_thread_checker_.IsCurrent()); - absl::optional plr; - absl::optional rplr; - { - rtc::CritScope lock(&packet_loss_tracker_cs_); - packet_loss_tracker_.OnPacketFeedbackVector(packet_feedback_vector); - plr = packet_loss_tracker_.GetPacketLossRate(); - rplr = packet_loss_tracker_.GetRecoverablePacketLossRate(); - } - // TODO(eladalon): If R/PLR go back to unknown, no indication is given that - // the previously sent value is no longer relevant. This will be taken care - // of with some refactoring which is now being done. - if (plr) { - channel_send_->OnTwccBasedUplinkPacketLossRate(*plr); - } - if (rplr) { - channel_send_->OnRecoverableUplinkPacketLossRate(*rplr); - } -} - void AudioSendStream::SetTransportOverhead( int transport_overhead_per_packet_bytes) { RTC_DCHECK(worker_thread_checker_.IsCurrent()); diff --git a/audio/audio_send_stream.h b/audio/audio_send_stream.h index 336a041160..fff3ee1a42 100644 --- a/audio/audio_send_stream.h +++ b/audio/audio_send_stream.h @@ -17,7 +17,6 @@ #include "audio/audio_level.h" #include "audio/channel_send.h" -#include "audio/transport_feedback_packet_loss_tracker.h" #include "call/audio_send_stream.h" #include "call/audio_state.h" #include "call/bitrate_allocator.h" @@ -54,7 +53,6 @@ class AudioState; class AudioSendStream final : public webrtc::AudioSendStream, public webrtc::BitrateAllocatorObserver, - public webrtc::PacketFeedbackObserver, public webrtc::OverheadObserver { public: AudioSendStream(Clock* clock, @@ -100,11 +98,6 @@ class AudioSendStream final : public webrtc::AudioSendStream, // Implements BitrateAllocatorObserver. uint32_t OnBitrateUpdated(BitrateAllocationUpdate update) override; - // From PacketFeedbackObserver. - void OnPacketAdded(uint32_t ssrc, uint16_t seq_num) override; - void OnPacketFeedbackVector( - const std::vector& packet_feedback_vector) override; - void SetTransportOverhead(int transport_overhead_per_packet_bytes); // OverheadObserver override reports audio packetization overhead from @@ -170,7 +163,6 @@ class AudioSendStream final : public webrtc::AudioSendStream, const bool send_side_bwe_with_overhead_; const AudioAllocationConfig allocation_settings_; - rtc::CriticalSection config_cs_; webrtc::AudioSendStream::Config config_; rtc::scoped_refptr audio_state_; const std::unique_ptr channel_send_; @@ -189,10 +181,6 @@ class AudioSendStream final : public webrtc::AudioSendStream, RTC_GUARDED_BY(worker_queue_); RtpTransportControllerSendInterface* const rtp_transport_; - rtc::CriticalSection packet_loss_tracker_cs_; - TransportFeedbackPacketLossTracker packet_loss_tracker_ - RTC_GUARDED_BY(&packet_loss_tracker_cs_); - RtpRtcp* rtp_rtcp_module_; absl::optional const suspended_rtp_state_; diff --git a/audio/audio_send_stream_unittest.cc b/audio/audio_send_stream_unittest.cc index ad959f2f08..6d6ec6a92b 100644 --- a/audio/audio_send_stream_unittest.cc +++ b/audio/audio_send_stream_unittest.cc @@ -700,29 +700,6 @@ TEST(AudioSendStreamTest, DontRecreateEncoder) { send_stream->Reconfigure(helper.config()); } -// Allow to check for race conditions under tsan. -// This mimicks the situation where 'ModuleProcessThread' (pacer thread) is -// launched by webrtc::RtpTransportControllerSend::RtpTransportControllerSend(). -TEST(AudioSendStreamTest, RaceFree) { - ConfigHelper helper(false, false); - // Sanity checks: copy-pasted from DontRecreateEncoder test. - EXPECT_CALL(*helper.channel_send(), SetEncoderForMock(_, _)) - .WillOnce(Return()); - - EXPECT_CALL(*helper.channel_send(), RegisterCngPayloadType(105, 8000)); - - helper.config().send_codec_spec = - AudioSendStream::Config::SendCodecSpec(9, kG722Format); - helper.config().send_codec_spec->cng_payload_type = 105; - auto send_stream = helper.CreateAudioSendStream(); - std::thread pacer([&]() { - send_stream->OnPacketAdded(/*ssrc*/ 0xcafe, - /*seq_num*/ 0xf00d); - }); - send_stream->Reconfigure(helper.config()); - pacer.join(); -} - TEST(AudioSendStreamTest, ReconfigureTransportCcResetsFirst) { ScopedFieldTrials field_trials("WebRTC-Audio-SendSideBwe/Enabled/"); ConfigHelper helper(false, true); diff --git a/audio/channel_send.cc b/audio/channel_send.cc index 569615bad6..184ea41458 100644 --- a/audio/channel_send.cc +++ b/audio/channel_send.cc @@ -163,15 +163,6 @@ class ChannelSend : public ChannelSendInterface, // packet. void ProcessAndEncodeAudio(std::unique_ptr audio_frame) override; - // The existence of this function alongside OnUplinkPacketLossRate is - // a compromise. We want the encoder to be agnostic of the PLR source, but - // we also don't want it to receive conflicting information from TWCC and - // from RTCP-XR. - void OnTwccBasedUplinkPacketLossRate(float packet_loss_rate) override; - - void OnRecoverableUplinkPacketLossRate( - float recoverable_packet_loss_rate) override; - int64_t GetRTT() const override; // E2EE Custom Audio Frame Encryption @@ -257,7 +248,6 @@ class ChannelSend : public ChannelSendInterface, rtc::ThreadChecker construction_thread_; - const bool use_twcc_plr_for_ana_; bool encoder_queue_is_active_ RTC_GUARDED_BY(encoder_queue_) = false; @@ -601,8 +591,6 @@ ChannelSend::ChannelSend(Clock* clock, rtp_packet_pacer_proxy_(new RtpPacketSenderProxy()), retransmission_rate_limiter_( new RateLimiter(clock, kMaxRetransmissionWindowMs)), - use_twcc_plr_for_ana_( - webrtc::field_trial::FindFullName("UseTwccPlrForAna") == "Enabled"), media_transport_config_(media_transport_config), frame_encryptor_(frame_encryptor), crypto_options_(crypto_options), @@ -790,27 +778,7 @@ int ChannelSend::GetBitrate() const { return configured_bitrate_bps_; } -void ChannelSend::OnTwccBasedUplinkPacketLossRate(float packet_loss_rate) { - RTC_DCHECK_RUN_ON(&worker_thread_checker_); - if (!use_twcc_plr_for_ana_) - return; - CallEncoder([&](AudioEncoder* encoder) { - encoder->OnReceivedUplinkPacketLossFraction(packet_loss_rate); - }); -} - -void ChannelSend::OnRecoverableUplinkPacketLossRate( - float recoverable_packet_loss_rate) { - RTC_DCHECK_RUN_ON(&worker_thread_checker_); - CallEncoder([&](AudioEncoder* encoder) { - encoder->OnReceivedUplinkRecoverablePacketLossFraction( - recoverable_packet_loss_rate); - }); -} - void ChannelSend::OnUplinkPacketLossRate(float packet_loss_rate) { - if (use_twcc_plr_for_ana_) - return; CallEncoder([&](AudioEncoder* encoder) { encoder->OnReceivedUplinkPacketLossFraction(packet_loss_rate); }); diff --git a/audio/channel_send.h b/audio/channel_send.h index 11f8332fd3..053b69a4e0 100644 --- a/audio/channel_send.h +++ b/audio/channel_send.h @@ -106,9 +106,6 @@ class ChannelSendInterface { std::unique_ptr audio_frame) = 0; virtual RtpRtcp* GetRtpRtcp() const = 0; - virtual void OnTwccBasedUplinkPacketLossRate(float packet_loss_rate) = 0; - virtual void OnRecoverableUplinkPacketLossRate( - float recoverable_packet_loss_rate) = 0; // In RTP we currently rely on RTCP packets (|ReceivedRTCPPacket|) to inform // about RTT. // In media transport we rely on the TargetTransferRateObserver instead. diff --git a/audio/transport_feedback_packet_loss_tracker.cc b/audio/transport_feedback_packet_loss_tracker.cc deleted file mode 100644 index 6f9ac9e5a2..0000000000 --- a/audio/transport_feedback_packet_loss_tracker.cc +++ /dev/null @@ -1,368 +0,0 @@ -/* - * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "audio/transport_feedback_packet_loss_tracker.h" - -#include -#include -#include - -#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" -#include "rtc_base/checks.h" -#include "rtc_base/numerics/mod_ops.h" - -namespace { -constexpr uint16_t kSeqNumHalf = 0x8000u; -void UpdateCounter(size_t* counter, bool increment) { - if (increment) { - RTC_DCHECK_LT(*counter, std::numeric_limits::max()); - ++(*counter); - } else { - RTC_DCHECK_GT(*counter, 0); - --(*counter); - } -} -} // namespace - -namespace webrtc { - -TransportFeedbackPacketLossTracker::TransportFeedbackPacketLossTracker( - int64_t max_window_size_ms, - size_t plr_min_num_acked_packets, - size_t rplr_min_num_acked_pairs) - : max_window_size_ms_(max_window_size_ms), - ref_packet_status_(packet_status_window_.begin()), - plr_state_(plr_min_num_acked_packets), - rplr_state_(rplr_min_num_acked_pairs) { - RTC_DCHECK_GT(max_window_size_ms, 0); - RTC_DCHECK_GT(plr_min_num_acked_packets, 0); - RTC_DCHECK_GT(rplr_min_num_acked_pairs, 0); - Reset(); -} - -TransportFeedbackPacketLossTracker::~TransportFeedbackPacketLossTracker() = - default; - -void TransportFeedbackPacketLossTracker::Reset() { - acked_packets_ = 0; - plr_state_.Reset(); - rplr_state_.Reset(); - packet_status_window_.clear(); - ref_packet_status_ = packet_status_window_.begin(); -} - -uint16_t TransportFeedbackPacketLossTracker::ReferenceSequenceNumber() const { - RTC_DCHECK(!packet_status_window_.empty()); - return ref_packet_status_->first; -} - -uint16_t TransportFeedbackPacketLossTracker::NewestSequenceNumber() const { - RTC_DCHECK(!packet_status_window_.empty()); - return PreviousPacketStatus(packet_status_window_.end())->first; -} - -void TransportFeedbackPacketLossTracker::OnPacketAdded(uint16_t seq_num, - int64_t send_time_ms) { - // Sanity - time can't flow backwards. - RTC_DCHECK( - packet_status_window_.empty() || - PreviousPacketStatus(packet_status_window_.end())->second.send_time_ms <= - send_time_ms); - - if (packet_status_window_.find(seq_num) != packet_status_window_.end() || - (!packet_status_window_.empty() && - ForwardDiff(seq_num, NewestSequenceNumber()) <= kSeqNumHalf)) { - // The only way for these two to happen is when the stream lies dormant for - // long enough for the sequence numbers to wrap. Everything in the window in - // such a case would be too old to use. - Reset(); - } - - // Maintain a window where the newest sequence number is at most 0x7fff away - // from the oldest, so that would could still distinguish old/new. - while (!packet_status_window_.empty() && - ForwardDiff(ref_packet_status_->first, seq_num) >= kSeqNumHalf) { - RemoveOldestPacketStatus(); - } - - SentPacket sent_packet(send_time_ms, PacketStatus::Unacked); - packet_status_window_.insert(packet_status_window_.end(), - std::make_pair(seq_num, sent_packet)); - - if (packet_status_window_.size() == 1) { - ref_packet_status_ = packet_status_window_.cbegin(); - } -} - -void TransportFeedbackPacketLossTracker::OnPacketFeedbackVector( - const std::vector& packet_feedback_vector) { - for (const PacketFeedback& packet : packet_feedback_vector) { - const auto& it = packet_status_window_.find(packet.sequence_number); - - // Packets which aren't at least marked as unacked either do not belong to - // this media stream, or have been shifted out of window. - if (it == packet_status_window_.end()) - continue; - - const bool lost = packet.arrival_time_ms == PacketFeedback::kNotReceived; - const PacketStatus packet_status = - lost ? PacketStatus::Lost : PacketStatus::Received; - - UpdatePacketStatus(it, packet_status); - } -} - -absl::optional TransportFeedbackPacketLossTracker::GetPacketLossRate() - const { - return plr_state_.GetMetric(); -} - -absl::optional -TransportFeedbackPacketLossTracker::GetRecoverablePacketLossRate() const { - return rplr_state_.GetMetric(); -} - -void TransportFeedbackPacketLossTracker::UpdatePacketStatus( - SentPacketStatusMap::iterator it, - PacketStatus new_status) { - if (it->second.status != PacketStatus::Unacked) { - // Normally, packets are sent (inserted into window as "unacked"), then we - // receive one feedback for them. - // But it is possible that a packet would receive two feedbacks. Then: - if (it->second.status == PacketStatus::Lost && - new_status == PacketStatus::Received) { - // If older status said that the packet was lost but newer one says it - // is received, we take the newer one. - UpdateMetrics(it, false); - it->second.status = - PacketStatus::Unacked; // For clarity; overwritten shortly. - } else { - // If the value is unchanged or if older status said that the packet was - // received but the newer one says it is lost, we ignore it. - // The standard allows for previously-reported packets to carry - // no report when the reports overlap, which also looks like the - // packet is being reported as lost. - return; - } - } - - // Change from UNACKED to RECEIVED/LOST. - it->second.status = new_status; - UpdateMetrics(it, true); - - // Remove packets from the beginning of the window until we only hold packets, - // be they acked or unacked, which are not more than |max_window_size_ms| - // older from the newest packet. (If the packet we're now inserting into the - // window isn't the newest, it would not trigger any removals; the newest - // already removed all relevant.) - while (ref_packet_status_ != packet_status_window_.end() && - (it->second.send_time_ms - ref_packet_status_->second.send_time_ms) > - max_window_size_ms_) { - RemoveOldestPacketStatus(); - } -} - -void TransportFeedbackPacketLossTracker::RemoveOldestPacketStatus() { - UpdateMetrics(ref_packet_status_, false); - const auto it = ref_packet_status_; - ref_packet_status_ = NextPacketStatus(it); - packet_status_window_.erase(it); -} - -void TransportFeedbackPacketLossTracker::UpdateMetrics( - ConstPacketStatusIterator it, - bool apply /* false = undo */) { - RTC_DCHECK(it != packet_status_window_.end()); - // Metrics are dependent on feedbacks from the other side. We don't want - // to update the metrics each time a packet is sent, except for the case - // when it shifts old sent-but-unacked-packets out of window. - RTC_DCHECK(!apply || it->second.status != PacketStatus::Unacked); - - if (it->second.status != PacketStatus::Unacked) { - UpdateCounter(&acked_packets_, apply); - } - - UpdatePlr(it, apply); - UpdateRplr(it, apply); -} - -void TransportFeedbackPacketLossTracker::UpdatePlr( - ConstPacketStatusIterator it, - bool apply /* false = undo */) { - switch (it->second.status) { - case PacketStatus::Unacked: - return; - case PacketStatus::Received: - UpdateCounter(&plr_state_.num_received_packets_, apply); - break; - case PacketStatus::Lost: - UpdateCounter(&plr_state_.num_lost_packets_, apply); - break; - default: - RTC_NOTREACHED(); - } -} - -void TransportFeedbackPacketLossTracker::UpdateRplr( - ConstPacketStatusIterator it, - bool apply /* false = undo */) { - if (it->second.status == PacketStatus::Unacked) { - // Unacked packets cannot compose a pair. - return; - } - - // Previous packet and current packet might compose a pair. - if (it != ref_packet_status_) { - const auto& prev = PreviousPacketStatus(it); - if (prev->second.status != PacketStatus::Unacked) { - UpdateCounter(&rplr_state_.num_acked_pairs_, apply); - if (prev->second.status == PacketStatus::Lost && - it->second.status == PacketStatus::Received) { - UpdateCounter(&rplr_state_.num_recoverable_losses_, apply); - } - } - } - - // Current packet and next packet might compose a pair. - const auto& next = NextPacketStatus(it); - if (next != packet_status_window_.end() && - next->second.status != PacketStatus::Unacked) { - UpdateCounter(&rplr_state_.num_acked_pairs_, apply); - if (it->second.status == PacketStatus::Lost && - next->second.status == PacketStatus::Received) { - UpdateCounter(&rplr_state_.num_recoverable_losses_, apply); - } - } -} - -TransportFeedbackPacketLossTracker::ConstPacketStatusIterator -TransportFeedbackPacketLossTracker::PreviousPacketStatus( - ConstPacketStatusIterator it) const { - RTC_DCHECK(it != ref_packet_status_); - if (it == packet_status_window_.end()) { - // This is to make PreviousPacketStatus(packet_status_window_.end()) point - // to the last element. - it = ref_packet_status_; - } - - if (it == packet_status_window_.begin()) { - // Due to the circular nature of sequence numbers, we let the iterator - // go to the end. - it = packet_status_window_.end(); - } - return --it; -} - -TransportFeedbackPacketLossTracker::ConstPacketStatusIterator -TransportFeedbackPacketLossTracker::NextPacketStatus( - ConstPacketStatusIterator it) const { - RTC_DCHECK(it != packet_status_window_.end()); - ++it; - if (it == packet_status_window_.end()) { - // Due to the circular nature of sequence numbers, we let the iterator - // goes back to the beginning. - it = packet_status_window_.begin(); - } - if (it == ref_packet_status_) { - // This is to make the NextPacketStatus of the last element to return the - // beyond-the-end iterator. - it = packet_status_window_.end(); - } - return it; -} - -// TODO(minyue): This method checks the states of this class do not misbehave. -// The method is used both in unit tests and a fuzzer test. The fuzzer test -// is present to help finding potential errors. Once the fuzzer test shows no -// error after long period, we can remove the fuzzer test, and move this method -// to unit test. -void TransportFeedbackPacketLossTracker::Validate() const { // Testing only! - RTC_CHECK_EQ(plr_state_.num_received_packets_ + plr_state_.num_lost_packets_, - acked_packets_); - RTC_CHECK_LE(acked_packets_, packet_status_window_.size()); - RTC_CHECK_LE(rplr_state_.num_recoverable_losses_, - rplr_state_.num_acked_pairs_); - RTC_CHECK_LE(rplr_state_.num_acked_pairs_, acked_packets_ - 1); - - size_t unacked_packets = 0; - size_t received_packets = 0; - size_t lost_packets = 0; - size_t acked_pairs = 0; - size_t recoverable_losses = 0; - - if (!packet_status_window_.empty()) { - ConstPacketStatusIterator it = ref_packet_status_; - do { - switch (it->second.status) { - case PacketStatus::Unacked: - ++unacked_packets; - break; - case PacketStatus::Received: - ++received_packets; - break; - case PacketStatus::Lost: - ++lost_packets; - break; - default: - RTC_NOTREACHED(); - } - - auto next = std::next(it); - if (next == packet_status_window_.end()) - next = packet_status_window_.begin(); - - if (next != ref_packet_status_) { // If we have a next packet... - RTC_CHECK_GE(next->second.send_time_ms, it->second.send_time_ms); - - if (it->second.status != PacketStatus::Unacked && - next->second.status != PacketStatus::Unacked) { - ++acked_pairs; - if (it->second.status == PacketStatus::Lost && - next->second.status == PacketStatus::Received) { - ++recoverable_losses; - } - } - } - - RTC_CHECK_LT(ForwardDiff(ReferenceSequenceNumber(), it->first), - kSeqNumHalf); - - it = next; - } while (it != ref_packet_status_); - } - - RTC_CHECK_EQ(plr_state_.num_received_packets_, received_packets); - RTC_CHECK_EQ(plr_state_.num_lost_packets_, lost_packets); - RTC_CHECK_EQ(packet_status_window_.size(), - unacked_packets + received_packets + lost_packets); - RTC_CHECK_EQ(rplr_state_.num_acked_pairs_, acked_pairs); - RTC_CHECK_EQ(rplr_state_.num_recoverable_losses_, recoverable_losses); -} - -absl::optional TransportFeedbackPacketLossTracker::PlrState::GetMetric() - const { - const size_t total = num_lost_packets_ + num_received_packets_; - if (total < min_num_acked_packets_) { - return absl::nullopt; - } else { - return static_cast(num_lost_packets_) / total; - } -} - -absl::optional TransportFeedbackPacketLossTracker::RplrState::GetMetric() - const { - if (num_acked_pairs_ < min_num_acked_pairs_) { - return absl::nullopt; - } else { - return static_cast(num_recoverable_losses_) / num_acked_pairs_; - } -} - -} // namespace webrtc diff --git a/audio/transport_feedback_packet_loss_tracker.h b/audio/transport_feedback_packet_loss_tracker.h deleted file mode 100644 index 180b64a16a..0000000000 --- a/audio/transport_feedback_packet_loss_tracker.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef AUDIO_TRANSPORT_FEEDBACK_PACKET_LOSS_TRACKER_H_ -#define AUDIO_TRANSPORT_FEEDBACK_PACKET_LOSS_TRACKER_H_ - -#include -#include - -#include "absl/types/optional.h" - -namespace webrtc { - -namespace rtcp { -class TransportFeedback; -} - -struct PacketFeedback; - -class TransportFeedbackPacketLossTracker final { - public: - // * We count up to |max_window_size_ms| from the sent - // time of the latest acked packet for the calculation of the metrics. - // * PLR (packet-loss-rate) is reliably computable once the statuses of - // |plr_min_num_acked_packets| packets are known. - // * RPLR (recoverable-packet-loss-rate) is reliably computable once the - // statuses of |rplr_min_num_acked_pairs| pairs are known. - TransportFeedbackPacketLossTracker(int64_t max_window_size_ms, - size_t plr_min_num_acked_packets, - size_t rplr_min_num_acked_pairs); - ~TransportFeedbackPacketLossTracker(); - - void OnPacketAdded(uint16_t seq_num, int64_t send_time_ms); - - void OnPacketFeedbackVector( - const std::vector& packet_feedbacks_vector); - - // Returns the packet loss rate, if the window has enough packet statuses to - // reliably compute it. Otherwise, returns empty. - absl::optional GetPacketLossRate() const; - - // Returns the first-order-FEC recoverable packet loss rate, if the window has - // enough status pairs to reliably compute it. Otherwise, returns empty. - absl::optional GetRecoverablePacketLossRate() const; - - // Verifies that the internal states are correct. Only used for tests. - void Validate() const; - - private: - // When a packet is sent, we memorize its association with the stream by - // marking it as (sent-but-so-far-) unacked. If we ever receive a feedback - // that reports it as received/lost, we update the state and - // metrics accordingly. - - enum class PacketStatus { Unacked = 0, Received = 1, Lost = 2 }; - struct SentPacket { - SentPacket(int64_t send_time_ms, PacketStatus status) - : send_time_ms(send_time_ms), status(status) {} - int64_t send_time_ms; - PacketStatus status; - }; - typedef std::map SentPacketStatusMap; - typedef SentPacketStatusMap::const_iterator ConstPacketStatusIterator; - - void Reset(); - - // ReferenceSequenceNumber() provides a sequence number that defines the - // order of packet reception info stored in |packet_status_window_|. In - // particular, given any sequence number |x|, - // (2^16 + x - ref_seq_num_) % 2^16 defines its actual position in - // |packet_status_window_|. - uint16_t ReferenceSequenceNumber() const; - uint16_t NewestSequenceNumber() const; - void UpdatePacketStatus(SentPacketStatusMap::iterator it, - PacketStatus new_status); - void RemoveOldestPacketStatus(); - - void UpdateMetrics(ConstPacketStatusIterator it, - bool apply /* false = undo */); - void UpdatePlr(ConstPacketStatusIterator it, bool apply /* false = undo */); - void UpdateRplr(ConstPacketStatusIterator it, bool apply /* false = undo */); - - ConstPacketStatusIterator PreviousPacketStatus( - ConstPacketStatusIterator it) const; - ConstPacketStatusIterator NextPacketStatus( - ConstPacketStatusIterator it) const; - - const int64_t max_window_size_ms_; - size_t acked_packets_; - - SentPacketStatusMap packet_status_window_; - // |ref_packet_status_| points to the oldest item in |packet_status_window_|. - ConstPacketStatusIterator ref_packet_status_; - - // Packet-loss-rate calculation (lost / all-known-packets). - struct PlrState { - explicit PlrState(size_t min_num_acked_packets) - : min_num_acked_packets_(min_num_acked_packets) { - Reset(); - } - void Reset() { - num_received_packets_ = 0; - num_lost_packets_ = 0; - } - absl::optional GetMetric() const; - const size_t min_num_acked_packets_; - size_t num_received_packets_; - size_t num_lost_packets_; - } plr_state_; - - // Recoverable packet loss calculation (first-order-FEC recoverable). - struct RplrState { - explicit RplrState(size_t min_num_acked_pairs) - : min_num_acked_pairs_(min_num_acked_pairs) { - Reset(); - } - void Reset() { - num_acked_pairs_ = 0; - num_recoverable_losses_ = 0; - } - absl::optional GetMetric() const; - // Recoverable packets are those which were lost, but immediately followed - // by a properly received packet. If that second packet carried FEC, - // the data from the former (lost) packet could be recovered. - // The RPLR is calculated as the fraction of such pairs (lost-received) out - // of all pairs of consecutive acked packets. - const size_t min_num_acked_pairs_; - size_t num_acked_pairs_; - size_t num_recoverable_losses_; - } rplr_state_; -}; - -} // namespace webrtc - -#endif // AUDIO_TRANSPORT_FEEDBACK_PACKET_LOSS_TRACKER_H_ diff --git a/audio/transport_feedback_packet_loss_tracker_unittest.cc b/audio/transport_feedback_packet_loss_tracker_unittest.cc deleted file mode 100644 index 5c3494fa7c..0000000000 --- a/audio/transport_feedback_packet_loss_tracker_unittest.cc +++ /dev/null @@ -1,569 +0,0 @@ -/* - * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "audio/transport_feedback_packet_loss_tracker.h" - -#include -#include -#include -#include - -#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" -#include "modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h" -#include "rtc_base/checks.h" -#include "test/gmock.h" -#include "test/gtest.h" - -namespace webrtc { - -namespace { - -constexpr int64_t kDefaultSendIntervalMs = 10; -constexpr int64_t kDefaultMaxWindowSizeMs = 500 * kDefaultSendIntervalMs; - -class TransportFeedbackPacketLossTrackerTest - : public ::testing::TestWithParam { - public: - TransportFeedbackPacketLossTrackerTest() = default; - virtual ~TransportFeedbackPacketLossTrackerTest() = default; - - protected: - void SendPackets(TransportFeedbackPacketLossTracker* tracker, - const std::vector& sequence_numbers, - int64_t send_time_interval_ms, - bool validate_all = true) { - RTC_CHECK_GE(send_time_interval_ms, 0); - for (uint16_t sequence_number : sequence_numbers) { - tracker->OnPacketAdded(sequence_number, time_ms_); - if (validate_all) { - tracker->Validate(); - } - time_ms_ += send_time_interval_ms; - } - - // We've either validated after each packet, or, for making sure the UT - // doesn't run too long, we might validate only at the end of the range. - if (!validate_all) { - tracker->Validate(); - } - } - - void SendPackets(TransportFeedbackPacketLossTracker* tracker, - uint16_t first_seq_num, - size_t num_of_packets, - int64_t send_time_interval_ms, - bool validate_all = true) { - RTC_CHECK_GE(send_time_interval_ms, 0); - std::vector sequence_numbers(num_of_packets); - std::iota(sequence_numbers.begin(), sequence_numbers.end(), first_seq_num); - SendPackets(tracker, sequence_numbers, send_time_interval_ms, validate_all); - } - - void AdvanceClock(int64_t time_delta_ms) { - RTC_CHECK_GT(time_delta_ms, 0); - time_ms_ += time_delta_ms; - } - - void AddTransportFeedbackAndValidate( - TransportFeedbackPacketLossTracker* tracker, - uint16_t base_sequence_num, - const std::vector& reception_status_vec) { - // Any positive integer signals reception. kNotReceived signals loss. - // Other values are just illegal. - constexpr int64_t kArrivalTimeMs = 1234; - - std::vector packet_feedback_vector; - uint16_t seq_num = base_sequence_num; - for (bool received : reception_status_vec) { - packet_feedback_vector.emplace_back(PacketFeedback( - received ? kArrivalTimeMs : PacketFeedback::kNotReceived, seq_num)); - ++seq_num; - } - - tracker->OnPacketFeedbackVector(packet_feedback_vector); - tracker->Validate(); - } - - // Checks that validty is as expected. If valid, checks also that - // value is as expected. - void ValidatePacketLossStatistics( - const TransportFeedbackPacketLossTracker& tracker, - absl::optional expected_plr, - absl::optional expected_rplr) { - // TODO(eladalon): Comparing the absl::optional directly would have - // given concise code, but less readable error messages. If we modify - // the way absl::optional is printed, we can get rid of this. - absl::optional plr = tracker.GetPacketLossRate(); - EXPECT_EQ(static_cast(expected_plr), static_cast(plr)); - if (expected_plr && plr) { - EXPECT_EQ(*expected_plr, *plr); - } - - absl::optional rplr = tracker.GetRecoverablePacketLossRate(); - EXPECT_EQ(static_cast(expected_rplr), static_cast(rplr)); - if (expected_rplr && rplr) { - EXPECT_EQ(*expected_rplr, *rplr); - } - } - - uint16_t base_{GetParam()}; - - private: - int64_t time_ms_{0}; -}; - -} // namespace - -// Sanity check on an empty window. -TEST_P(TransportFeedbackPacketLossTrackerTest, EmptyWindow) { - TransportFeedbackPacketLossTracker tracker(kDefaultMaxWindowSizeMs, 5, 5); - - // PLR and RPLR reported as unknown before reception of first feedback. - ValidatePacketLossStatistics(tracker, absl::nullopt, absl::nullopt); -} - -// A feedback received for an empty window has no effect. -TEST_P(TransportFeedbackPacketLossTrackerTest, EmptyWindowFeedback) { - TransportFeedbackPacketLossTracker tracker(kDefaultMaxWindowSizeMs, 3, 2); - - // Feedback doesn't correspond to any packets - ignored. - AddTransportFeedbackAndValidate(&tracker, base_, {true, false, true}); - ValidatePacketLossStatistics(tracker, absl::nullopt, absl::nullopt); - - // After the packets are transmitted, acking them would have an effect. - SendPackets(&tracker, base_, 3, kDefaultSendIntervalMs); - AddTransportFeedbackAndValidate(&tracker, base_, {true, false, true}); - ValidatePacketLossStatistics(tracker, 1.0f / 3.0f, 0.5f); -} - -// Sanity check on partially filled window. -TEST_P(TransportFeedbackPacketLossTrackerTest, PartiallyFilledWindow) { - TransportFeedbackPacketLossTracker tracker(kDefaultMaxWindowSizeMs, 5, 4); - - // PLR unknown before minimum window size reached. - // RPLR unknown before minimum pairs reached. - // Expected window contents: [] -> [1001]. - SendPackets(&tracker, base_, 3, kDefaultSendIntervalMs); - AddTransportFeedbackAndValidate(&tracker, base_, {true, false, false, true}); - ValidatePacketLossStatistics(tracker, absl::nullopt, absl::nullopt); -} - -// Sanity check on minimum filled window - PLR known, RPLR unknown. -TEST_P(TransportFeedbackPacketLossTrackerTest, PlrMinimumFilledWindow) { - TransportFeedbackPacketLossTracker tracker(kDefaultMaxWindowSizeMs, 5, 5); - - // PLR correctly calculated after minimum window size reached. - // RPLR not necessarily known at that time (not if min-pairs not reached). - // Expected window contents: [] -> [10011]. - SendPackets(&tracker, base_, 5, kDefaultSendIntervalMs); - AddTransportFeedbackAndValidate(&tracker, base_, - {true, false, false, true, true}); - ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, absl::nullopt); -} - -// Sanity check on minimum filled window - PLR unknown, RPLR known. -TEST_P(TransportFeedbackPacketLossTrackerTest, RplrMinimumFilledWindow) { - TransportFeedbackPacketLossTracker tracker(kDefaultMaxWindowSizeMs, 6, 4); - - // RPLR correctly calculated after minimum pairs reached. - // PLR not necessarily known at that time (not if min window not reached). - // Expected window contents: [] -> [10011]. - SendPackets(&tracker, base_, 5, kDefaultSendIntervalMs); - AddTransportFeedbackAndValidate(&tracker, base_, - {true, false, false, true, true}); - ValidatePacketLossStatistics(tracker, absl::nullopt, 1.0f / 4.0f); -} - -// If packets are sent close enough together that the clock reading for both -// is the same, that's handled properly. -TEST_P(TransportFeedbackPacketLossTrackerTest, SameSentTime) { - TransportFeedbackPacketLossTracker tracker(kDefaultMaxWindowSizeMs, 3, 2); - - // Expected window contents: [] -> [101]. - SendPackets(&tracker, base_, 3, 0); // Note: time interval = 0ms. - AddTransportFeedbackAndValidate(&tracker, base_, {true, false, true}); - - ValidatePacketLossStatistics(tracker, 1.0f / 3.0f, 0.5f); -} - -// Additional reports update PLR and RPLR. -TEST_P(TransportFeedbackPacketLossTrackerTest, ExtendWindow) { - TransportFeedbackPacketLossTracker tracker(kDefaultMaxWindowSizeMs, 5, 5); - - SendPackets(&tracker, base_, 25, kDefaultSendIntervalMs); - - // Expected window contents: [] -> [10011]. - AddTransportFeedbackAndValidate(&tracker, base_, - {true, false, false, true, true}); - ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, absl::nullopt); - - // Expected window contents: [10011] -> [1001110101]. - AddTransportFeedbackAndValidate(&tracker, base_ + 5, - {true, false, true, false, true}); - ValidatePacketLossStatistics(tracker, 4.0f / 10.0f, 3.0f / 9.0f); - - // Expected window contents: [1001110101] -> [1001110101-GAP-10001]. - AddTransportFeedbackAndValidate(&tracker, base_ + 20, - {true, false, false, false, true}); - ValidatePacketLossStatistics(tracker, 7.0f / 15.0f, 4.0f / 13.0f); -} - -// Correct calculation with different packet lengths. -TEST_P(TransportFeedbackPacketLossTrackerTest, DifferentSentIntervals) { - TransportFeedbackPacketLossTracker tracker(kDefaultMaxWindowSizeMs, 5, 4); - - int64_t frames[] = {20, 60, 120, 20, 60}; - for (size_t i = 0; i < sizeof(frames) / sizeof(frames[0]); i++) { - SendPackets(&tracker, {static_cast(base_ + i)}, frames[i]); - } - - // Expected window contents: [] -> [10011]. - AddTransportFeedbackAndValidate(&tracker, base_, - {true, false, false, true, true}); - ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); -} - -// The window retains information up to sent times that exceed the the max -// window size. The oldest packets get shifted out of window to make room -// for the newer ones. -TEST_P(TransportFeedbackPacketLossTrackerTest, MaxWindowSize) { - TransportFeedbackPacketLossTracker tracker(4 * kDefaultSendIntervalMs, 5, 1); - - SendPackets(&tracker, base_, 6, kDefaultSendIntervalMs, true); - - // Up to the maximum time-span retained (first + 4 * kDefaultSendIntervalMs). - // Expected window contents: [] -> [01001]. - AddTransportFeedbackAndValidate(&tracker, base_, - {false, true, false, false, true}); - ValidatePacketLossStatistics(tracker, 3.0f / 5.0f, 2.0f / 4.0f); - - // After the maximum time-span, older entries are discarded to accommodate - // newer ones. - // Expected window contents: [01001] -> [10011]. - AddTransportFeedbackAndValidate(&tracker, base_ + 5, {true}); - ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); -} - -// All packets received. -TEST_P(TransportFeedbackPacketLossTrackerTest, AllReceived) { - TransportFeedbackPacketLossTracker tracker(kDefaultMaxWindowSizeMs, 5, 4); - - // Expected window contents: [] -> [11111]. - SendPackets(&tracker, base_, 5, kDefaultSendIntervalMs); - AddTransportFeedbackAndValidate(&tracker, base_, - {true, true, true, true, true}); - ValidatePacketLossStatistics(tracker, 0.0f, 0.0f); -} - -// All packets lost. -TEST_P(TransportFeedbackPacketLossTrackerTest, AllLost) { - TransportFeedbackPacketLossTracker tracker(kDefaultMaxWindowSizeMs, 5, 4); - - // Note: The last packet in the feedback does not belong to the stream. - // It's only there because we're not allowed to end a feedback with a loss. - // Expected window contents: [] -> [00000]. - SendPackets(&tracker, base_, 5, kDefaultSendIntervalMs); - AddTransportFeedbackAndValidate(&tracker, base_, - {false, false, false, false, false, true}); - ValidatePacketLossStatistics(tracker, 1.0f, 0.0f); -} - -// Repeated reports are ignored. -TEST_P(TransportFeedbackPacketLossTrackerTest, ReportRepetition) { - TransportFeedbackPacketLossTracker tracker(kDefaultMaxWindowSizeMs, 5, 4); - - SendPackets(&tracker, base_, 5, kDefaultSendIntervalMs); - - // Expected window contents: [] -> [10011]. - AddTransportFeedbackAndValidate(&tracker, base_, - {true, false, false, true, true}); - ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); - - // Repeat entire previous feedback - // Expected window contents: [10011] -> [10011]. - AddTransportFeedbackAndValidate(&tracker, base_, - {true, false, false, true, true}); - ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); -} - -// Report overlap. -TEST_P(TransportFeedbackPacketLossTrackerTest, ReportOverlap) { - TransportFeedbackPacketLossTracker tracker(kDefaultMaxWindowSizeMs, 5, 1); - - SendPackets(&tracker, base_, 15, kDefaultSendIntervalMs); - - // Expected window contents: [] -> [10011]. - AddTransportFeedbackAndValidate(&tracker, base_, - {true, false, false, true, true}); - ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); - - // Expected window contents: [10011] -> [1001101]. - AddTransportFeedbackAndValidate(&tracker, base_ + 3, - {true, true, false, true}); - ValidatePacketLossStatistics(tracker, 3.0f / 7.0f, 2.0f / 6.0f); -} - -// Report conflict. -TEST_P(TransportFeedbackPacketLossTrackerTest, ReportConflict) { - TransportFeedbackPacketLossTracker tracker(kDefaultMaxWindowSizeMs, 5, 4); - - SendPackets(&tracker, base_, 15, 10); - - // Expected window contents: [] -> [01001]. - AddTransportFeedbackAndValidate(&tracker, base_, - {false, true, false, false, true}); - ValidatePacketLossStatistics(tracker, 3.0f / 5.0f, 2.0f / 4.0f); - - // Expected window contents: [01001] -> [11101]. - // While false->true will be applied, true -> false will be ignored. - AddTransportFeedbackAndValidate(&tracker, base_, {true, false, true}); - ValidatePacketLossStatistics(tracker, 1.0f / 5.0f, 1.0f / 4.0f); -} - -// Skipped packets treated as unknown (not lost). -TEST_P(TransportFeedbackPacketLossTrackerTest, SkippedPackets) { - TransportFeedbackPacketLossTracker tracker(200 * kDefaultSendIntervalMs, 5, - 1); - - SendPackets(&tracker, base_, 200, kDefaultSendIntervalMs); - - // Expected window contents: [] -> [10011]. - AddTransportFeedbackAndValidate(&tracker, base_, - {true, false, false, true, true}); - ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); - - // Expected window contents: [10011] -> [10011-GAP-101]. - AddTransportFeedbackAndValidate(&tracker, base_ + 100, {true, false, true}); - ValidatePacketLossStatistics(tracker, 3.0f / 8.0f, 2.0f / 6.0f); -} - -// Moving a window, if it excludes some old acked messages, can leave -// in-window unacked messages intact, and ready to be used later. -TEST_P(TransportFeedbackPacketLossTrackerTest, MovedWindowRetainsRelevantInfo) { - constexpr int64_t max_window_size_ms = 100; - TransportFeedbackPacketLossTracker tracker(max_window_size_ms, 5, 1); - - // Note: All messages in this test are sent 1ms apart from each other. - // Therefore, the delta in sequence numbers equals the timestamps delta. - SendPackets(&tracker, base_, 4 * max_window_size_ms, 1); - - // Expected window contents: [] -> [10101]. - AddTransportFeedbackAndValidate(&tracker, base_, - {true, false, true, false, true}); - ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 2.0f / 4.0f); - - // Expected window contents: [10101] -> [100011]. - const int64_t moved_oldest_acked = base_ + 2 * max_window_size_ms; - const std::vector feedback = {true, false, false, false, true, true}; - AddTransportFeedbackAndValidate(&tracker, moved_oldest_acked, feedback); - ValidatePacketLossStatistics(tracker, 3.0f / 6.0f, 1.0f / 5.0f); - - // Having acked |feedback.size()| starting with |moved_oldest_acked|, the - // newest of the acked ones is now: - const int64_t moved_newest_acked = moved_oldest_acked + feedback.size() - 1; - - // Messages that *are* more than the span-limit away from the newest - // acked message *are* too old. Acking them would have no effect. - AddTransportFeedbackAndValidate( - &tracker, moved_newest_acked - max_window_size_ms - 1, {true}); - ValidatePacketLossStatistics(tracker, 3.0f / 6.0f, 1.0f / 5.0f); - - // Messages that are *not* more than the span-limit away from the newest - // acked message are *not* too old. Acking them would have an effect. - AddTransportFeedbackAndValidate( - &tracker, moved_newest_acked - max_window_size_ms, {true}); - ValidatePacketLossStatistics(tracker, 3.0f / 7.0f, 1.0f / 5.0f); -} - -// Inserting feedback into the middle of a window works correctly - can -// complete two pairs. -TEST_P(TransportFeedbackPacketLossTrackerTest, InsertionCompletesTwoPairs) { - TransportFeedbackPacketLossTracker tracker(150 * kDefaultSendIntervalMs, 5, - 1); - - SendPackets(&tracker, base_, 15, kDefaultSendIntervalMs); - - // Expected window contents: [] -> [10111]. - AddTransportFeedbackAndValidate(&tracker, base_, - {true, false, true, true, true}); - ValidatePacketLossStatistics(tracker, 1.0f / 5.0f, 1.0f / 4.0f); - - // Expected window contents: [10111] -> [10111-GAP-10101]. - AddTransportFeedbackAndValidate(&tracker, base_ + 7, - {true, false, true, false, true}); - ValidatePacketLossStatistics(tracker, 3.0f / 10.0f, 3.0f / 8.0f); - - // Insert in between, closing the gap completely. - // Expected window contents: [10111-GAP-10101] -> [101110110101]. - AddTransportFeedbackAndValidate(&tracker, base_ + 5, {false, true}); - ValidatePacketLossStatistics(tracker, 4.0f / 12.0f, 4.0f / 11.0f); -} - -// Sequence number gaps are not gaps in reception. However, gaps in reception -// are still possible, if a packet which WAS sent on the stream is not acked. -TEST_P(TransportFeedbackPacketLossTrackerTest, SanityGapsInSequenceNumbers) { - TransportFeedbackPacketLossTracker tracker(50 * kDefaultSendIntervalMs, 5, 1); - - SendPackets( - &tracker, - {static_cast(base_), static_cast(base_ + 2), - static_cast(base_ + 4), static_cast(base_ + 6), - static_cast(base_ + 8)}, - kDefaultSendIntervalMs); - - // Gaps in sequence numbers not considered as gaps in window, because only - // those sequence numbers which were associated with the stream count. - // Expected window contents: [] -> [11011]. - AddTransportFeedbackAndValidate( - // Note: Left packets belong to this stream, right ones ignored. - &tracker, base_, - {true, false, true, false, false, false, true, false, true, true}); - ValidatePacketLossStatistics(tracker, 1.0f / 5.0f, 1.0f / 4.0f); - - // Create gap by sending [base + 10] but not acking it. - // Note: Acks for [base + 11] and [base + 13] ignored (other stream). - // Expected window contents: [11011] -> [11011-GAP-01]. - SendPackets( - &tracker, - {static_cast(base_ + 10), static_cast(base_ + 12), - static_cast(base_ + 14)}, - kDefaultSendIntervalMs); - AddTransportFeedbackAndValidate(&tracker, base_ + 11, - {false, false, false, true, true}); - ValidatePacketLossStatistics(tracker, 2.0f / 7.0f, 2.0f / 5.0f); -} - -// The window cannot span more than 0x8000 in sequence numbers, regardless -// of time stamps and ack/unacked status. -TEST_P(TransportFeedbackPacketLossTrackerTest, MaxUnackedPackets) { - TransportFeedbackPacketLossTracker tracker(0x10000, 4, 1); - - SendPackets(&tracker, base_, 0x2000, 1, false); - - // Expected window contents: [] -> [10011]. - AddTransportFeedbackAndValidate(&tracker, base_, - {true, false, false, true, true}); - ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); - - // Sending more unacked packets, up to 0x7fff from the base, does not - // move the window or discard any information. - SendPackets(&tracker, static_cast(base_ + 0x8000 - 0x2000), 0x2000, - 1, false); - ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); - - // Sending more unacked packets, up to 0x7fff from the base, does not - // move the window or discard any information. - // Expected window contents: [10011] -> [0011]. - SendPackets(&tracker, static_cast(base_ + 0x8000), 1, 1); - ValidatePacketLossStatistics(tracker, 2.0f / 4.0f, 1.0f / 3.0f); -} - -// The window holds acked packets up until the difference in timestamps between -// the oldest and newest reaches the configured maximum. Once this maximum -// is exceeded, old packets are shifted out of window until the maximum is -// once again observed. -TEST_P(TransportFeedbackPacketLossTrackerTest, TimeDifferenceMaximumObserved) { - constexpr int64_t max_window_size_ms = 500; - TransportFeedbackPacketLossTracker tracker(max_window_size_ms, 3, 1); - - // Note: All messages in this test are sent 1ms apart from each other. - // Therefore, the delta in sequence numbers equals the timestamps delta. - - // Baseline - window has acked messages. - // Expected window contents: [] -> [01101]. - const std::vector feedback = {false, true, true, false, true}; - SendPackets(&tracker, base_, feedback.size(), 1); - AddTransportFeedbackAndValidate(&tracker, base_, feedback); - ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 2.0f / 4.0f); - - // Test - window base not moved. - // Expected window contents: [01101] -> [011011]. - AdvanceClock(max_window_size_ms - feedback.size()); - SendPackets(&tracker, static_cast(base_ + feedback.size()), 1, 1); - AddTransportFeedbackAndValidate( - &tracker, static_cast(base_ + feedback.size()), {true}); - ValidatePacketLossStatistics(tracker, 2.0f / 6.0f, 2.0f / 5.0f); - - // Another packet, sent 1ms later, would already be too late. The window will - // be moved, but only after the ACK is received. - const uint16_t new_packet_seq_num = - static_cast(base_ + feedback.size() + 1); - SendPackets(&tracker, {new_packet_seq_num}, 1); - ValidatePacketLossStatistics(tracker, 2.0f / 6.0f, 2.0f / 5.0f); - // Expected window contents: [011011] -> [110111]. - AddTransportFeedbackAndValidate(&tracker, new_packet_seq_num, {true}); - ValidatePacketLossStatistics(tracker, 1.0f / 6.0f, 1.0f / 5.0f); -} - -TEST_P(TransportFeedbackPacketLossTrackerTest, RepeatedSeqNumResetsWindow) { - TransportFeedbackPacketLossTracker tracker(50 * kDefaultSendIntervalMs, 2, 1); - - // Baseline - window has acked messages. - // Expected window contents: [] -> [01101]. - SendPackets(&tracker, base_, 5, kDefaultSendIntervalMs); - AddTransportFeedbackAndValidate(&tracker, base_, - {false, true, true, false, true}); - ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 2.0f / 4.0f); - - // A reset occurs. - SendPackets(&tracker, {static_cast(base_ + 2)}, - kDefaultSendIntervalMs); - ValidatePacketLossStatistics(tracker, absl::nullopt, absl::nullopt); -} - -// The window is reset by the sending of a packet which is 0x8000 or more -// away from the newest packet acked/unacked packet. -TEST_P(TransportFeedbackPacketLossTrackerTest, - SendAfterLongSuspensionResetsWindow) { - TransportFeedbackPacketLossTracker tracker(50 * kDefaultSendIntervalMs, 2, 1); - - // Baseline - window has acked messages. - // Expected window contents: [] -> [01101]. - SendPackets(&tracker, base_, 5, kDefaultSendIntervalMs); - AddTransportFeedbackAndValidate(&tracker, base_, - {false, true, true, false, true}); - ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 2.0f / 4.0f); - - // A reset occurs. - SendPackets(&tracker, {static_cast(base_ + 5 + 0x8000)}, - kDefaultSendIntervalMs); - ValidatePacketLossStatistics(tracker, absl::nullopt, absl::nullopt); -} - -#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) -TEST(TransportFeedbackPacketLossTrackerTest, InvalidConfigMaxWindowSize) { - EXPECT_DEATH(TransportFeedbackPacketLossTracker tracker(0, 20, 10), ""); -} - -TEST(TransportFeedbackPacketLossTrackerTest, InvalidConfigPlrMinAcked) { - EXPECT_DEATH(TransportFeedbackPacketLossTracker tracker(5000, 0, 10), ""); -} - -TEST(TransportFeedbackPacketLossTrackerTest, InvalidConfigRplrMinPairs) { - EXPECT_DEATH(TransportFeedbackPacketLossTracker tracker(5000, 20, 0), ""); -} - -TEST(TransportFeedbackPacketLossTrackerTest, TimeCantFlowBackwards) { - TransportFeedbackPacketLossTracker tracker(5000, 2, 1); - tracker.OnPacketAdded(100, 0); - tracker.OnPacketAdded(101, 2); - EXPECT_DEATH(tracker.OnPacketAdded(102, 1), ""); -} -#endif - -// All tests are run multiple times with various baseline sequence number, -// to weed out potential bugs with wrap-around handling. -constexpr uint16_t kBases[] = {0x0000, 0x3456, 0xc032, 0xfffe}; - -INSTANTIATE_TEST_SUITE_P(_, - TransportFeedbackPacketLossTrackerTest, - ::testing::ValuesIn(kBases)); - -} // namespace webrtc diff --git a/modules/audio_coding/BUILD.gn b/modules/audio_coding/BUILD.gn index 0dda20bf51..2cad71c734 100644 --- a/modules/audio_coding/BUILD.gn +++ b/modules/audio_coding/BUILD.gn @@ -890,8 +890,6 @@ rtc_library("audio_network_adaptor") { "audio_network_adaptor/event_log_writer.h", "audio_network_adaptor/fec_controller_plr_based.cc", "audio_network_adaptor/fec_controller_plr_based.h", - "audio_network_adaptor/fec_controller_rplr_based.cc", - "audio_network_adaptor/fec_controller_rplr_based.h", "audio_network_adaptor/frame_length_controller.cc", "audio_network_adaptor/frame_length_controller.h", "audio_network_adaptor/include/audio_network_adaptor.h", @@ -1920,7 +1918,6 @@ if (rtc_include_tests) { "audio_network_adaptor/dtx_controller_unittest.cc", "audio_network_adaptor/event_log_writer_unittest.cc", "audio_network_adaptor/fec_controller_plr_based_unittest.cc", - "audio_network_adaptor/fec_controller_rplr_based_unittest.cc", "audio_network_adaptor/frame_length_controller_unittest.cc", "audio_network_adaptor/util/threshold_curve_unittest.cc", "codecs/builtin_audio_decoder_factory_unittest.cc", diff --git a/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.cc b/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.cc index 11f93e617a..64163f9118 100644 --- a/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.cc +++ b/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.cc @@ -72,18 +72,6 @@ void AudioNetworkAdaptorImpl::SetUplinkPacketLossFraction( UpdateNetworkMetrics(network_metrics); } -void AudioNetworkAdaptorImpl::SetUplinkRecoverablePacketLossFraction( - float uplink_recoverable_packet_loss_fraction) { - last_metrics_.uplink_recoverable_packet_loss_fraction = - uplink_recoverable_packet_loss_fraction; - DumpNetworkMetrics(); - - Controller::NetworkMetrics network_metrics; - network_metrics.uplink_recoverable_packet_loss_fraction = - uplink_recoverable_packet_loss_fraction; - UpdateNetworkMetrics(network_metrics); -} - void AudioNetworkAdaptorImpl::SetRtt(int rtt_ms) { last_metrics_.rtt_ms = rtt_ms; DumpNetworkMetrics(); diff --git a/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.h b/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.h index e7cd056599..1c91fa19a8 100644 --- a/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.h +++ b/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.h @@ -48,9 +48,6 @@ class AudioNetworkAdaptorImpl final : public AudioNetworkAdaptor { void SetUplinkPacketLossFraction(float uplink_packet_loss_fraction) override; - void SetUplinkRecoverablePacketLossFraction( - float uplink_recoverable_packet_loss_fraction) override; - void SetRtt(int rtt_ms) override; void SetTargetAudioBitrate(int target_audio_bitrate_bps) override; diff --git a/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl_unittest.cc b/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl_unittest.cc index 8ca26bb3ad..606237d303 100644 --- a/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl_unittest.cc +++ b/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl_unittest.cc @@ -41,10 +41,7 @@ MATCHER_P(NetworkMetricsIs, metric, "") { arg.target_audio_bitrate_bps == metric.target_audio_bitrate_bps && arg.rtt_ms == metric.rtt_ms && arg.overhead_bytes_per_packet == metric.overhead_bytes_per_packet && - arg.uplink_packet_loss_fraction == - metric.uplink_packet_loss_fraction && - arg.uplink_recoverable_packet_loss_fraction == - metric.uplink_recoverable_packet_loss_fraction; + arg.uplink_packet_loss_fraction == metric.uplink_packet_loss_fraction; } MATCHER_P(IsRtcEventAnaConfigEqualTo, config, "") { @@ -139,17 +136,6 @@ TEST(AudioNetworkAdaptorImplTest, states.audio_network_adaptor->SetUplinkPacketLossFraction(kPacketLoss); } -TEST(AudioNetworkAdaptorImplTest, - UpdateNetworkMetricsIsCalledOnSetUplinkRecoverablePacketLossFraction) { - auto states = CreateAudioNetworkAdaptor(); - constexpr float kRecoverablePacketLoss = 0.1f; - Controller::NetworkMetrics check; - check.uplink_recoverable_packet_loss_fraction = kRecoverablePacketLoss; - SetExpectCallToUpdateNetworkMetrics(states.mock_controllers, check); - states.audio_network_adaptor->SetUplinkRecoverablePacketLossFraction( - kRecoverablePacketLoss); -} - TEST(AudioNetworkAdaptorImplTest, UpdateNetworkMetricsIsCalledOnSetRtt) { auto states = CreateAudioNetworkAdaptor(); constexpr int kRtt = 100; @@ -216,7 +202,6 @@ TEST(AudioNetworkAdaptorImplTest, constexpr int kBandwidth = 16000; constexpr float kPacketLoss = 0.7f; - const auto kRecoverablePacketLoss = 0.2f; constexpr int kRtt = 100; constexpr int kTargetAudioBitrate = 15000; constexpr size_t kOverhead = 64; @@ -238,11 +223,6 @@ TEST(AudioNetworkAdaptorImplTest, fake_clock.AdvanceTime(TimeDelta::ms(50)); timestamp_check += 50; - check.uplink_recoverable_packet_loss_fraction = kRecoverablePacketLoss; - EXPECT_CALL(*states.mock_debug_dump_writer, - DumpNetworkMetrics(NetworkMetricsIs(check), timestamp_check)); - states.audio_network_adaptor->SetUplinkRecoverablePacketLossFraction( - kRecoverablePacketLoss); fake_clock.AdvanceTime(TimeDelta::ms(200)); timestamp_check += 200; diff --git a/modules/audio_coding/audio_network_adaptor/controller.h b/modules/audio_coding/audio_network_adaptor/controller.h index 19d8599d5e..b70ada01a4 100644 --- a/modules/audio_coding/audio_network_adaptor/controller.h +++ b/modules/audio_coding/audio_network_adaptor/controller.h @@ -23,7 +23,6 @@ class Controller { ~NetworkMetrics(); absl::optional uplink_bandwidth_bps; absl::optional uplink_packet_loss_fraction; - absl::optional uplink_recoverable_packet_loss_fraction; absl::optional target_audio_bitrate_bps; absl::optional rtt_ms; absl::optional overhead_bytes_per_packet; diff --git a/modules/audio_coding/audio_network_adaptor/controller_manager.cc b/modules/audio_coding/audio_network_adaptor/controller_manager.cc index f22df54165..c7aad1da87 100644 --- a/modules/audio_coding/audio_network_adaptor/controller_manager.cc +++ b/modules/audio_coding/audio_network_adaptor/controller_manager.cc @@ -19,10 +19,10 @@ #include "modules/audio_coding/audio_network_adaptor/debug_dump_writer.h" #include "modules/audio_coding/audio_network_adaptor/dtx_controller.h" #include "modules/audio_coding/audio_network_adaptor/fec_controller_plr_based.h" -#include "modules/audio_coding/audio_network_adaptor/fec_controller_rplr_based.h" #include "modules/audio_coding/audio_network_adaptor/frame_length_controller.h" #include "modules/audio_coding/audio_network_adaptor/util/threshold_curve.h" #include "rtc_base/ignore_wundef.h" +#include "rtc_base/logging.h" #include "rtc_base/time_utils.h" #if WEBRTC_ENABLE_PROTOBUF @@ -74,43 +74,6 @@ std::unique_ptr CreateFecControllerPlrBased( config.time_constant_ms()))); } -std::unique_ptr CreateFecControllerRplrBased( - const audio_network_adaptor::config::FecControllerRplrBased& config, - bool initial_fec_enabled) { - RTC_CHECK(config.has_fec_enabling_threshold()); - RTC_CHECK(config.has_fec_disabling_threshold()); - - auto& fec_enabling_threshold = config.fec_enabling_threshold(); - RTC_CHECK(fec_enabling_threshold.has_low_bandwidth_bps()); - RTC_CHECK(fec_enabling_threshold.has_low_bandwidth_recoverable_packet_loss()); - RTC_CHECK(fec_enabling_threshold.has_high_bandwidth_bps()); - RTC_CHECK( - fec_enabling_threshold.has_high_bandwidth_recoverable_packet_loss()); - - auto& fec_disabling_threshold = config.fec_disabling_threshold(); - RTC_CHECK(fec_disabling_threshold.has_low_bandwidth_bps()); - RTC_CHECK( - fec_disabling_threshold.has_low_bandwidth_recoverable_packet_loss()); - RTC_CHECK(fec_disabling_threshold.has_high_bandwidth_bps()); - RTC_CHECK( - fec_disabling_threshold.has_high_bandwidth_recoverable_packet_loss()); - - return std::unique_ptr( - new FecControllerRplrBased(FecControllerRplrBased::Config( - initial_fec_enabled, - ThresholdCurve( - fec_enabling_threshold.low_bandwidth_bps(), - fec_enabling_threshold.low_bandwidth_recoverable_packet_loss(), - fec_enabling_threshold.high_bandwidth_bps(), - fec_enabling_threshold.high_bandwidth_recoverable_packet_loss()), - ThresholdCurve( - fec_disabling_threshold.low_bandwidth_bps(), - fec_disabling_threshold.low_bandwidth_recoverable_packet_loss(), - fec_disabling_threshold.high_bandwidth_bps(), - fec_disabling_threshold - .high_bandwidth_recoverable_packet_loss())))); -} - std::unique_ptr CreateFrameLengthController( const audio_network_adaptor::config::FrameLengthController& config, rtc::ArrayView encoder_frame_lengths_ms, @@ -291,9 +254,9 @@ std::unique_ptr ControllerManagerImpl::Create( controller_config.fec_controller(), initial_fec_enabled); break; case audio_network_adaptor::config::Controller::kFecControllerRplrBased: - controller = CreateFecControllerRplrBased( - controller_config.fec_controller_rplr_based(), initial_fec_enabled); - break; + // FecControllerRplrBased has been removed and can't be used anymore. + RTC_NOTREACHED(); + continue; case audio_network_adaptor::config::Controller::kFrameLengthController: controller = CreateFrameLengthController( controller_config.frame_length_controller(), diff --git a/modules/audio_coding/audio_network_adaptor/debug_dump_writer.cc b/modules/audio_coding/audio_network_adaptor/debug_dump_writer.cc index 6daefa5951..669cf5ee53 100644 --- a/modules/audio_coding/audio_network_adaptor/debug_dump_writer.cc +++ b/modules/audio_coding/audio_network_adaptor/debug_dump_writer.cc @@ -105,11 +105,6 @@ void DebugDumpWriterImpl::DumpNetworkMetrics( if (metrics.rtt_ms) dump_metrics->set_rtt_ms(*metrics.rtt_ms); - if (metrics.uplink_recoverable_packet_loss_fraction) { - dump_metrics->set_uplink_recoverable_packet_loss_fraction( - *metrics.uplink_recoverable_packet_loss_fraction); - } - DumpEventToFile(event, &dump_file_); #endif // WEBRTC_ENABLE_PROTOBUF } diff --git a/modules/audio_coding/audio_network_adaptor/fec_controller_rplr_based.cc b/modules/audio_coding/audio_network_adaptor/fec_controller_rplr_based.cc deleted file mode 100644 index 6c30b8f2c0..0000000000 --- a/modules/audio_coding/audio_network_adaptor/fec_controller_rplr_based.cc +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "modules/audio_coding/audio_network_adaptor/fec_controller_rplr_based.h" - -#include "rtc_base/checks.h" - -namespace webrtc { - -FecControllerRplrBased::Config::Config( - bool initial_fec_enabled, - const ThresholdCurve& fec_enabling_threshold, - const ThresholdCurve& fec_disabling_threshold) - : initial_fec_enabled(initial_fec_enabled), - fec_enabling_threshold(fec_enabling_threshold), - fec_disabling_threshold(fec_disabling_threshold) {} - -FecControllerRplrBased::FecControllerRplrBased(const Config& config) - : config_(config), fec_enabled_(config.initial_fec_enabled) { - RTC_DCHECK(config_.fec_disabling_threshold <= config_.fec_enabling_threshold); -} - -FecControllerRplrBased::~FecControllerRplrBased() = default; - -void FecControllerRplrBased::UpdateNetworkMetrics( - const NetworkMetrics& network_metrics) { - if (network_metrics.uplink_bandwidth_bps) - uplink_bandwidth_bps_ = network_metrics.uplink_bandwidth_bps; - if (network_metrics.uplink_recoverable_packet_loss_fraction) { - uplink_recoverable_packet_loss_ = - network_metrics.uplink_recoverable_packet_loss_fraction; - } -} - -void FecControllerRplrBased::MakeDecision(AudioEncoderRuntimeConfig* config) { - RTC_DCHECK(!config->enable_fec); - RTC_DCHECK(!config->uplink_packet_loss_fraction); - - fec_enabled_ = fec_enabled_ ? !FecDisablingDecision() : FecEnablingDecision(); - - config->enable_fec = fec_enabled_; - config->uplink_packet_loss_fraction = - uplink_recoverable_packet_loss_ ? *uplink_recoverable_packet_loss_ : 0.0; -} - -bool FecControllerRplrBased::FecEnablingDecision() const { - if (!uplink_bandwidth_bps_ || !uplink_recoverable_packet_loss_) { - return false; - } else { - // Enable when above the curve or exactly on it. - return !config_.fec_enabling_threshold.IsBelowCurve( - {static_cast(*uplink_bandwidth_bps_), - *uplink_recoverable_packet_loss_}); - } -} - -bool FecControllerRplrBased::FecDisablingDecision() const { - if (!uplink_bandwidth_bps_ || !uplink_recoverable_packet_loss_) { - return false; - } else { - // Disable when below the curve. - return config_.fec_disabling_threshold.IsBelowCurve( - {static_cast(*uplink_bandwidth_bps_), - *uplink_recoverable_packet_loss_}); - } -} - -} // namespace webrtc diff --git a/modules/audio_coding/audio_network_adaptor/fec_controller_rplr_based.h b/modules/audio_coding/audio_network_adaptor/fec_controller_rplr_based.h deleted file mode 100644 index c547bff18d..0000000000 --- a/modules/audio_coding/audio_network_adaptor/fec_controller_rplr_based.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_FEC_CONTROLLER_RPLR_BASED_H_ -#define MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_FEC_CONTROLLER_RPLR_BASED_H_ - -#include "absl/types/optional.h" -#include "modules/audio_coding/audio_network_adaptor/controller.h" -#include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor_config.h" -#include "modules/audio_coding/audio_network_adaptor/util/threshold_curve.h" -#include "rtc_base/constructor_magic.h" - -namespace webrtc { - -class FecControllerRplrBased final : public Controller { - public: - struct Config { - // |fec_enabling_threshold| defines a curve, above which FEC should be - // enabled. |fec_disabling_threshold| defines a curve, under which FEC - // should be disabled. See below - // - // recoverable - // packet-loss ^ | | - // | | | FEC - // | \ \ ON - // | FEC \ \_______ fec_enabling_threshold - // | OFF \_________ fec_disabling_threshold - // |-----------------> bandwidth - Config(bool initial_fec_enabled, - const ThresholdCurve& fec_enabling_threshold, - const ThresholdCurve& fec_disabling_threshold); - bool initial_fec_enabled; - ThresholdCurve fec_enabling_threshold; - ThresholdCurve fec_disabling_threshold; - }; - - explicit FecControllerRplrBased(const Config& config); - - ~FecControllerRplrBased() override; - - void UpdateNetworkMetrics(const NetworkMetrics& network_metrics) override; - - void MakeDecision(AudioEncoderRuntimeConfig* config) override; - - private: - bool FecEnablingDecision() const; - bool FecDisablingDecision() const; - - const Config config_; - bool fec_enabled_; - absl::optional uplink_bandwidth_bps_; - absl::optional uplink_recoverable_packet_loss_; - - RTC_DISALLOW_COPY_AND_ASSIGN(FecControllerRplrBased); -}; - -} // namespace webrtc - -#endif // MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_FEC_CONTROLLER_RPLR_BASED_H_ diff --git a/modules/audio_coding/audio_network_adaptor/fec_controller_rplr_based_unittest.cc b/modules/audio_coding/audio_network_adaptor/fec_controller_rplr_based_unittest.cc deleted file mode 100644 index c51d561a35..0000000000 --- a/modules/audio_coding/audio_network_adaptor/fec_controller_rplr_based_unittest.cc +++ /dev/null @@ -1,522 +0,0 @@ -/* - * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "modules/audio_coding/audio_network_adaptor/fec_controller_rplr_based.h" - -#include -#include - -#include "test/gtest.h" - -namespace webrtc { - -namespace { - -// The test uses the following settings: -// -// recoverable ^ -// packet-loss | | | -// | A| C| FEC -// | \ \ ON -// | FEC \ D\_______ -// | OFF B\_________ -// |-----------------> bandwidth -// -// A : (kDisablingBandwidthLow, kDisablingRecoverablePacketLossAtLowBw) -// B : (kDisablingBandwidthHigh, kDisablingRecoverablePacketLossAtHighBw) -// C : (kEnablingBandwidthLow, kEnablingRecoverablePacketLossAtLowBw) -// D : (kEnablingBandwidthHigh, kEnablingRecoverablePacketLossAtHighBw) - -constexpr int kDisablingBandwidthLow = 15000; -constexpr float kDisablingRecoverablePacketLossAtLowBw = 0.08f; -constexpr int kDisablingBandwidthHigh = 64000; -constexpr float kDisablingRecoverablePacketLossAtHighBw = 0.01f; -constexpr int kEnablingBandwidthLow = 17000; -constexpr float kEnablingRecoverablePacketLossAtLowBw = 0.1f; -constexpr int kEnablingBandwidthHigh = 64000; -constexpr float kEnablingRecoverablePacketLossAtHighBw = 0.05f; - -constexpr float kEpsilon = 1e-5f; - -absl::optional GetRandomProbabilityOrUnknown() { - std::random_device rd; - std::mt19937 generator(rd()); - std::uniform_real_distribution<> distribution(0, 1); - - return (distribution(generator) < 0.2) - ? absl::nullopt - : absl::optional(distribution(generator)); -} - -std::unique_ptr CreateFecControllerRplrBased( - bool initial_fec_enabled) { - return std::unique_ptr( - new FecControllerRplrBased(FecControllerRplrBased::Config( - initial_fec_enabled, - ThresholdCurve( - kEnablingBandwidthLow, kEnablingRecoverablePacketLossAtLowBw, - kEnablingBandwidthHigh, kEnablingRecoverablePacketLossAtHighBw), - ThresholdCurve(kDisablingBandwidthLow, - kDisablingRecoverablePacketLossAtLowBw, - kDisablingBandwidthHigh, - kDisablingRecoverablePacketLossAtHighBw)))); -} - -void UpdateNetworkMetrics( - FecControllerRplrBased* controller, - const absl::optional& uplink_bandwidth_bps, - const absl::optional& uplink_packet_loss, - const absl::optional& uplink_recoveralbe_packet_loss) { - // UpdateNetworkMetrics can accept multiple network metric updates at once. - // However, currently, the most used case is to update one metric at a time. - // To reflect this fact, we separate the calls. - if (uplink_bandwidth_bps) { - Controller::NetworkMetrics network_metrics; - network_metrics.uplink_bandwidth_bps = uplink_bandwidth_bps; - controller->UpdateNetworkMetrics(network_metrics); - } - if (uplink_packet_loss) { - Controller::NetworkMetrics network_metrics; - network_metrics.uplink_packet_loss_fraction = uplink_packet_loss; - controller->UpdateNetworkMetrics(network_metrics); - } - if (uplink_recoveralbe_packet_loss) { - Controller::NetworkMetrics network_metrics; - network_metrics.uplink_recoverable_packet_loss_fraction = - uplink_recoveralbe_packet_loss; - controller->UpdateNetworkMetrics(network_metrics); - } -} - -void UpdateNetworkMetrics( - FecControllerRplrBased* controller, - const absl::optional& uplink_bandwidth_bps, - const absl::optional& uplink_recoveralbe_packet_loss) { - // FecControllerRplrBased doesn't currently use the PLR (general packet-loss - // rate) at all. (This might be changed in the future.) The unit-tests will - // use a random value (including unknown), to show this does not interfere. - UpdateNetworkMetrics(controller, uplink_bandwidth_bps, - GetRandomProbabilityOrUnknown(), - uplink_recoveralbe_packet_loss); -} - -// Checks that the FEC decision and |uplink_packet_loss_fraction| given by -// |states->controller->MakeDecision| matches |expected_enable_fec| and -// |expected_uplink_packet_loss_fraction|, respectively. -void CheckDecision(FecControllerRplrBased* controller, - bool expected_enable_fec, - float expected_uplink_packet_loss_fraction) { - AudioEncoderRuntimeConfig config; - controller->MakeDecision(&config); - - // Less compact than comparing optionals, but yields more readable errors. - EXPECT_TRUE(config.enable_fec); - if (config.enable_fec) { - EXPECT_EQ(expected_enable_fec, *config.enable_fec); - } - EXPECT_TRUE(config.uplink_packet_loss_fraction); - if (config.uplink_packet_loss_fraction) { - EXPECT_EQ(expected_uplink_packet_loss_fraction, - *config.uplink_packet_loss_fraction); - } -} - -} // namespace - -TEST(FecControllerRplrBasedTest, OutputInitValueBeforeAnyInputsAreReceived) { - for (bool initial_fec_enabled : {false, true}) { - auto controller = CreateFecControllerRplrBased(initial_fec_enabled); - CheckDecision(controller.get(), initial_fec_enabled, 0); - } -} - -TEST(FecControllerRplrBasedTest, OutputInitValueWhenUplinkBandwidthUnknown) { - // Regardless of the initial FEC state and the recoverable-packet-loss - // rate, the initial FEC state is maintained as long as the BWE is unknown. - for (bool initial_fec_enabled : {false, true}) { - for (float recoverable_packet_loss : - {kDisablingRecoverablePacketLossAtHighBw - kEpsilon, - kDisablingRecoverablePacketLossAtHighBw, - kDisablingRecoverablePacketLossAtHighBw + kEpsilon, - kEnablingRecoverablePacketLossAtHighBw - kEpsilon, - kEnablingRecoverablePacketLossAtHighBw, - kEnablingRecoverablePacketLossAtHighBw + kEpsilon}) { - auto controller = CreateFecControllerRplrBased(initial_fec_enabled); - UpdateNetworkMetrics(controller.get(), absl::nullopt, - recoverable_packet_loss); - CheckDecision(controller.get(), initial_fec_enabled, - recoverable_packet_loss); - } - } -} - -TEST(FecControllerRplrBasedTest, - OutputInitValueWhenUplinkRecoverablePacketLossFractionUnknown) { - // Regardless of the initial FEC state and the BWE, the initial FEC state - // is maintained as long as the recoverable-packet-loss rate is unknown. - for (bool initial_fec_enabled : {false, true}) { - for (int bandwidth : {kDisablingBandwidthLow - 1, kDisablingBandwidthLow, - kDisablingBandwidthLow + 1, kEnablingBandwidthLow - 1, - kEnablingBandwidthLow, kEnablingBandwidthLow + 1}) { - auto controller = CreateFecControllerRplrBased(initial_fec_enabled); - UpdateNetworkMetrics(controller.get(), bandwidth, absl::nullopt); - CheckDecision(controller.get(), initial_fec_enabled, 0.0); - } - } -} - -TEST(FecControllerRplrBasedTest, EnableFecForHighBandwidth) { - auto controller = CreateFecControllerRplrBased(false); - UpdateNetworkMetrics(controller.get(), kEnablingBandwidthHigh, - kEnablingRecoverablePacketLossAtHighBw); - CheckDecision(controller.get(), true, kEnablingRecoverablePacketLossAtHighBw); -} - -TEST(FecControllerRplrBasedTest, UpdateMultipleNetworkMetricsAtOnce) { - // This test is similar to EnableFecForHighBandwidth. But instead of - // using ::UpdateNetworkMetrics(...), which calls - // FecControllerRplrBasedTest::UpdateNetworkMetrics(...) multiple times, we - // we call it only once. This is to verify that - // FecControllerRplrBasedTest::UpdateNetworkMetrics(...) can handle multiple - // network updates at once. This is, however, not a common use case in current - // audio_network_adaptor_impl.cc. - auto controller = CreateFecControllerRplrBased(false); - Controller::NetworkMetrics network_metrics; - network_metrics.uplink_bandwidth_bps = kEnablingBandwidthHigh; - network_metrics.uplink_packet_loss_fraction = GetRandomProbabilityOrUnknown(); - network_metrics.uplink_recoverable_packet_loss_fraction = - kEnablingRecoverablePacketLossAtHighBw; - controller->UpdateNetworkMetrics(network_metrics); - CheckDecision(controller.get(), true, kEnablingRecoverablePacketLossAtHighBw); -} - -TEST(FecControllerRplrBasedTest, MaintainFecOffForHighBandwidth) { - auto controller = CreateFecControllerRplrBased(false); - constexpr float kRecoverablePacketLoss = - kEnablingRecoverablePacketLossAtHighBw * 0.99f; - UpdateNetworkMetrics(controller.get(), kEnablingBandwidthHigh, - kRecoverablePacketLoss); - CheckDecision(controller.get(), false, kRecoverablePacketLoss); -} - -TEST(FecControllerRplrBasedTest, EnableFecForMediumBandwidth) { - auto controller = CreateFecControllerRplrBased(false); - constexpr float kRecoverablePacketLoss = - (kEnablingRecoverablePacketLossAtLowBw + - kEnablingRecoverablePacketLossAtHighBw) / - 2.0; - UpdateNetworkMetrics(controller.get(), - (kEnablingBandwidthHigh + kEnablingBandwidthLow) / 2, - kRecoverablePacketLoss); - CheckDecision(controller.get(), true, kRecoverablePacketLoss); -} - -TEST(FecControllerRplrBasedTest, MaintainFecOffForMediumBandwidth) { - auto controller = CreateFecControllerRplrBased(false); - constexpr float kRecoverablePacketLoss = - kEnablingRecoverablePacketLossAtLowBw * 0.49f + - kEnablingRecoverablePacketLossAtHighBw * 0.51f; - UpdateNetworkMetrics(controller.get(), - (kEnablingBandwidthHigh + kEnablingBandwidthLow) / 2, - kRecoverablePacketLoss); - CheckDecision(controller.get(), false, kRecoverablePacketLoss); -} - -TEST(FecControllerRplrBasedTest, EnableFecForLowBandwidth) { - auto controller = CreateFecControllerRplrBased(false); - UpdateNetworkMetrics(controller.get(), kEnablingBandwidthLow, - kEnablingRecoverablePacketLossAtLowBw); - CheckDecision(controller.get(), true, kEnablingRecoverablePacketLossAtLowBw); -} - -TEST(FecControllerRplrBasedTest, MaintainFecOffForLowBandwidth) { - auto controller = CreateFecControllerRplrBased(false); - constexpr float kRecoverablePacketLoss = - kEnablingRecoverablePacketLossAtLowBw * 0.99f; - UpdateNetworkMetrics(controller.get(), kEnablingBandwidthLow, - kRecoverablePacketLoss); - CheckDecision(controller.get(), false, kRecoverablePacketLoss); -} - -TEST(FecControllerRplrBasedTest, MaintainFecOffForVeryLowBandwidth) { - auto controller = CreateFecControllerRplrBased(false); - // Below |kEnablingBandwidthLow|, no recoverable packet loss fraction can - // cause FEC to turn on. - UpdateNetworkMetrics(controller.get(), kEnablingBandwidthLow - 1, 1.0); - CheckDecision(controller.get(), false, 1.0); -} - -TEST(FecControllerRplrBasedTest, DisableFecForHighBandwidth) { - auto controller = CreateFecControllerRplrBased(true); - constexpr float kRecoverablePacketLoss = - kDisablingRecoverablePacketLossAtHighBw - kEpsilon; - UpdateNetworkMetrics(controller.get(), kDisablingBandwidthHigh, - kRecoverablePacketLoss); - CheckDecision(controller.get(), false, kRecoverablePacketLoss); -} - -TEST(FecControllerRplrBasedTest, MaintainFecOnForHighBandwidth) { - // Note: Disabling happens when the value is strictly below the threshold. - auto controller = CreateFecControllerRplrBased(true); - UpdateNetworkMetrics(controller.get(), kDisablingBandwidthHigh, - kDisablingRecoverablePacketLossAtHighBw); - CheckDecision(controller.get(), true, - kDisablingRecoverablePacketLossAtHighBw); -} - -TEST(FecControllerRplrBasedTest, DisableFecOnMediumBandwidth) { - auto controller = CreateFecControllerRplrBased(true); - constexpr float kRecoverablePacketLoss = - ((kDisablingRecoverablePacketLossAtLowBw + - kDisablingRecoverablePacketLossAtHighBw) / - 2.0f) - - kEpsilon; - UpdateNetworkMetrics(controller.get(), - (kDisablingBandwidthHigh + kDisablingBandwidthLow) / 2, - kRecoverablePacketLoss); - CheckDecision(controller.get(), false, kRecoverablePacketLoss); -} - -TEST(FecControllerRplrBasedTest, MaintainFecOnForMediumBandwidth) { - auto controller = CreateFecControllerRplrBased(true); - constexpr float kRecoverablePacketLoss = - kDisablingRecoverablePacketLossAtLowBw * 0.51f + - kDisablingRecoverablePacketLossAtHighBw * 0.49f - kEpsilon; - UpdateNetworkMetrics(controller.get(), - (kEnablingBandwidthHigh + kDisablingBandwidthLow) / 2, - kRecoverablePacketLoss); - CheckDecision(controller.get(), true, kRecoverablePacketLoss); -} - -TEST(FecControllerRplrBasedTest, DisableFecForLowBandwidth) { - auto controller = CreateFecControllerRplrBased(true); - constexpr float kRecoverablePacketLoss = - kDisablingRecoverablePacketLossAtLowBw - kEpsilon; - UpdateNetworkMetrics(controller.get(), kDisablingBandwidthLow, - kRecoverablePacketLoss); - CheckDecision(controller.get(), false, kRecoverablePacketLoss); -} - -TEST(FecControllerRplrBasedTest, DisableFecForVeryLowBandwidth) { - auto controller = CreateFecControllerRplrBased(true); - // Below |kEnablingBandwidthLow|, any recoverable packet loss fraction can - // cause FEC to turn off. - UpdateNetworkMetrics(controller.get(), kDisablingBandwidthLow - 1, 1.0); - CheckDecision(controller.get(), false, 1.0); -} - -TEST(FecControllerRplrBasedTest, CheckBehaviorOnChangingNetworkMetrics) { - // In this test, we let the network metrics to traverse from 1 to 5. - // - // recoverable ^ - // packet-loss | 1 | | - // | | 2| - // | \ \ 3 - // | \4 \_______ - // | \_________ - // |---------5-------> bandwidth - - auto controller = CreateFecControllerRplrBased(true); - UpdateNetworkMetrics(controller.get(), kDisablingBandwidthLow - 1, 1.0); - CheckDecision(controller.get(), false, 1.0); - - UpdateNetworkMetrics(controller.get(), kEnablingBandwidthLow, - kEnablingRecoverablePacketLossAtLowBw * 0.99f); - CheckDecision(controller.get(), false, - kEnablingRecoverablePacketLossAtLowBw * 0.99f); - - UpdateNetworkMetrics(controller.get(), kEnablingBandwidthHigh, - kEnablingRecoverablePacketLossAtHighBw); - CheckDecision(controller.get(), true, kEnablingRecoverablePacketLossAtHighBw); - - UpdateNetworkMetrics(controller.get(), kDisablingBandwidthHigh, - kDisablingRecoverablePacketLossAtHighBw); - CheckDecision(controller.get(), true, - kDisablingRecoverablePacketLossAtHighBw); - - UpdateNetworkMetrics(controller.get(), kDisablingBandwidthHigh + 1, 0.0); - CheckDecision(controller.get(), false, 0.0); -} - -TEST(FecControllerRplrBasedTest, CheckBehaviorOnSpecialCurves) { - // We test a special configuration, where the points to define the FEC - // enabling/disabling curves are placed like the following, otherwise the test - // is the same as CheckBehaviorOnChangingNetworkMetrics. - // - // recoverable ^ - // packet-loss | | | - // | | C| - // | | | - // | | D|_______ - // | A|___B______ - // |-----------------> bandwidth - - constexpr int kEnablingBandwidthHigh = kEnablingBandwidthLow; - constexpr float kDisablingRecoverablePacketLossAtLowBw = - kDisablingRecoverablePacketLossAtHighBw; - FecControllerRplrBased controller(FecControllerRplrBased::Config( - true, - ThresholdCurve( - kEnablingBandwidthLow, kEnablingRecoverablePacketLossAtLowBw, - kEnablingBandwidthHigh, kEnablingRecoverablePacketLossAtHighBw), - ThresholdCurve( - kDisablingBandwidthLow, kDisablingRecoverablePacketLossAtLowBw, - kDisablingBandwidthHigh, kDisablingRecoverablePacketLossAtHighBw))); - - UpdateNetworkMetrics(&controller, kDisablingBandwidthLow - 1, 1.0); - CheckDecision(&controller, false, 1.0); - - UpdateNetworkMetrics(&controller, kEnablingBandwidthLow, - kEnablingRecoverablePacketLossAtHighBw * 0.99f); - CheckDecision(&controller, false, - kEnablingRecoverablePacketLossAtHighBw * 0.99f); - - UpdateNetworkMetrics(&controller, kEnablingBandwidthHigh, - kEnablingRecoverablePacketLossAtHighBw); - CheckDecision(&controller, true, kEnablingRecoverablePacketLossAtHighBw); - - UpdateNetworkMetrics(&controller, kDisablingBandwidthHigh, - kDisablingRecoverablePacketLossAtHighBw); - CheckDecision(&controller, true, kDisablingRecoverablePacketLossAtHighBw); - - UpdateNetworkMetrics(&controller, kDisablingBandwidthHigh + 1, 0.0); - CheckDecision(&controller, false, 0.0); -} - -TEST(FecControllerRplrBasedTest, SingleThresholdCurveForEnablingAndDisabling) { - // Note: To avoid numerical errors, keep kRecoverablePacketLossAtLowBw and - // kRecoverablePacketLossAthighBw as (negative) integer powers of 2. - // This is mostly relevant for the O3 case. - constexpr int kBandwidthLow = 10000; - constexpr float kRecoverablePacketLossAtLowBw = 0.25f; - constexpr int kBandwidthHigh = 20000; - constexpr float kRecoverablePacketLossAtHighBw = 0.125f; - auto curve = ThresholdCurve(kBandwidthLow, kRecoverablePacketLossAtLowBw, - kBandwidthHigh, kRecoverablePacketLossAtHighBw); - - // B* stands for "below-curve", O* for "on-curve", and A* for "above-curve". - // - // // - // recoverable ^ // - // packet-loss | | // - // | B1 O1 // - // | | // - // | O2 // - // | \ A1 // - // | \ // - // | O3 A2 // - // | B2 \ // - // | \ // - // | O4--O5---- // - // | // - // | B3 // - // |-----------------> bandwidth // - - struct NetworkState { - int bandwidth; - float recoverable_packet_loss; - }; - - std::vector below{ - {kBandwidthLow - 1, kRecoverablePacketLossAtLowBw + 0.1f}, // B1 - {(kBandwidthLow + kBandwidthHigh) / 2, - (kRecoverablePacketLossAtLowBw + kRecoverablePacketLossAtHighBw) / 2 - - kEpsilon}, // B2 - {kBandwidthHigh + 1, kRecoverablePacketLossAtHighBw - kEpsilon} // B3 - }; - - std::vector on{ - {kBandwidthLow, kRecoverablePacketLossAtLowBw + 0.1f}, // O1 - {kBandwidthLow, kRecoverablePacketLossAtLowBw}, // O2 - {(kBandwidthLow + kBandwidthHigh) / 2, - (kRecoverablePacketLossAtLowBw + kRecoverablePacketLossAtHighBw) / - 2}, // O3 - {kBandwidthHigh, kRecoverablePacketLossAtHighBw}, // O4 - {kBandwidthHigh + 1, kRecoverablePacketLossAtHighBw}, // O5 - }; - - std::vector above{ - {(kBandwidthLow + kBandwidthHigh) / 2, - (kRecoverablePacketLossAtLowBw + kRecoverablePacketLossAtHighBw) / 2 + - kEpsilon}, // A1 - {kBandwidthHigh + 1, kRecoverablePacketLossAtHighBw + kEpsilon}, // A2 - }; - - // Test that FEC is turned off whenever we're below the curve, independent - // of the starting FEC state. - for (NetworkState net_state : below) { - for (bool initial_fec_enabled : {false, true}) { - FecControllerRplrBased controller( - FecControllerRplrBased::Config(initial_fec_enabled, curve, curve)); - UpdateNetworkMetrics(&controller, net_state.bandwidth, - net_state.recoverable_packet_loss); - CheckDecision(&controller, false, net_state.recoverable_packet_loss); - } - } - - // Test that FEC is turned on whenever we're on the curve or above it, - // independent of the starting FEC state. - for (const std::vector& states_list : {on, above}) { - for (NetworkState net_state : states_list) { - for (bool initial_fec_enabled : {false, true}) { - FecControllerRplrBased controller( - FecControllerRplrBased::Config(initial_fec_enabled, curve, curve)); - UpdateNetworkMetrics(&controller, net_state.bandwidth, - net_state.recoverable_packet_loss); - CheckDecision(&controller, true, net_state.recoverable_packet_loss); - } - } - } -} - -TEST(FecControllerRplrBasedTest, FecAlwaysOff) { - ThresholdCurve always_off_curve(0, 1.0f + kEpsilon, 0, 1.0f + kEpsilon); - for (bool initial_fec_enabled : {false, true}) { - for (int bandwidth : {0, 10000}) { - for (float recoverable_packet_loss : {0.0f, 0.5f, 1.0f}) { - FecControllerRplrBased controller(FecControllerRplrBased::Config( - initial_fec_enabled, always_off_curve, always_off_curve)); - UpdateNetworkMetrics(&controller, bandwidth, recoverable_packet_loss); - CheckDecision(&controller, false, recoverable_packet_loss); - } - } - } -} - -TEST(FecControllerRplrBasedTest, FecAlwaysOn) { - ThresholdCurve always_on_curve(0, 0.0f, 0, 0.0f); - for (bool initial_fec_enabled : {false, true}) { - for (int bandwidth : {0, 10000}) { - for (float recoverable_packet_loss : {0.0f, 0.5f, 1.0f}) { - FecControllerRplrBased controller(FecControllerRplrBased::Config( - initial_fec_enabled, always_on_curve, always_on_curve)); - UpdateNetworkMetrics(&controller, bandwidth, recoverable_packet_loss); - CheckDecision(&controller, true, recoverable_packet_loss); - } - } - } -} - -#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) -TEST(FecControllerRplrBasedDeathTest, InvalidConfig) { - EXPECT_DEATH( - FecControllerRplrBased controller(FecControllerRplrBased::Config( - true, - ThresholdCurve( - kDisablingBandwidthLow - 1, kEnablingRecoverablePacketLossAtLowBw, - kEnablingBandwidthHigh, kEnablingRecoverablePacketLossAtHighBw), - ThresholdCurve(kDisablingBandwidthLow, - kDisablingRecoverablePacketLossAtLowBw, - kDisablingBandwidthHigh, - kDisablingRecoverablePacketLossAtHighBw))), - "Check failed"); -} -#endif -} // namespace webrtc diff --git a/modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h b/modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h index c11279ea90..346ed5db1a 100644 --- a/modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h +++ b/modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h @@ -29,9 +29,6 @@ class AudioNetworkAdaptor { virtual void SetUplinkPacketLossFraction( float uplink_packet_loss_fraction) = 0; - virtual void SetUplinkRecoverablePacketLossFraction( - float uplink_recoverable_packet_loss_fraction) = 0; - virtual void SetRtt(int rtt_ms) = 0; virtual void SetTargetAudioBitrate(int target_audio_bitrate_bps) = 0; diff --git a/modules/audio_coding/audio_network_adaptor/mock/mock_audio_network_adaptor.h b/modules/audio_coding/audio_network_adaptor/mock/mock_audio_network_adaptor.h index 15dc741e29..8c048496ca 100644 --- a/modules/audio_coding/audio_network_adaptor/mock/mock_audio_network_adaptor.h +++ b/modules/audio_coding/audio_network_adaptor/mock/mock_audio_network_adaptor.h @@ -26,9 +26,6 @@ class MockAudioNetworkAdaptor : public AudioNetworkAdaptor { MOCK_METHOD1(SetUplinkPacketLossFraction, void(float uplink_packet_loss_fraction)); - MOCK_METHOD1(SetUplinkRecoverablePacketLossFraction, - void(float uplink_recoverable_packet_loss_fraction)); - MOCK_METHOD1(SetRtt, void(int rtt_ms)); MOCK_METHOD1(SetTargetAudioBitrate, void(int target_audio_bitrate_bps)); diff --git a/modules/audio_coding/codecs/cng/audio_encoder_cng.cc b/modules/audio_coding/codecs/cng/audio_encoder_cng.cc index a4e0ffb2fd..86d3f38b49 100644 --- a/modules/audio_coding/codecs/cng/audio_encoder_cng.cc +++ b/modules/audio_coding/codecs/cng/audio_encoder_cng.cc @@ -52,8 +52,6 @@ class AudioEncoderCng final : public AudioEncoder { override; void OnReceivedUplinkPacketLossFraction( float uplink_packet_loss_fraction) override; - void OnReceivedUplinkRecoverablePacketLossFraction( - float uplink_recoverable_packet_loss_fraction) override; void OnReceivedUplinkBandwidth( int target_audio_bitrate_bps, absl::optional bwe_period_ms) override; @@ -220,12 +218,6 @@ void AudioEncoderCng::OnReceivedUplinkPacketLossFraction( uplink_packet_loss_fraction); } -void AudioEncoderCng::OnReceivedUplinkRecoverablePacketLossFraction( - float uplink_recoverable_packet_loss_fraction) { - speech_encoder_->OnReceivedUplinkRecoverablePacketLossFraction( - uplink_recoverable_packet_loss_fraction); -} - void AudioEncoderCng::OnReceivedUplinkBandwidth( int target_audio_bitrate_bps, absl::optional bwe_period_ms) { diff --git a/modules/audio_coding/codecs/opus/audio_encoder_opus.cc b/modules/audio_coding/codecs/opus/audio_encoder_opus.cc index 39ddd73da7..ee0e51e8fd 100644 --- a/modules/audio_coding/codecs/opus/audio_encoder_opus.cc +++ b/modules/audio_coding/codecs/opus/audio_encoder_opus.cc @@ -593,15 +593,6 @@ void AudioEncoderOpusImpl::OnReceivedUplinkPacketLossFraction( ApplyAudioNetworkAdaptor(); } -void AudioEncoderOpusImpl::OnReceivedUplinkRecoverablePacketLossFraction( - float uplink_recoverable_packet_loss_fraction) { - if (!audio_network_adaptor_) - return; - audio_network_adaptor_->SetUplinkRecoverablePacketLossFraction( - uplink_recoverable_packet_loss_fraction); - ApplyAudioNetworkAdaptor(); -} - void AudioEncoderOpusImpl::OnReceivedUplinkBandwidth( int target_audio_bitrate_bps, absl::optional bwe_period_ms, diff --git a/modules/audio_coding/codecs/opus/audio_encoder_opus.h b/modules/audio_coding/codecs/opus/audio_encoder_opus.h index 85ec05007c..66c489f79b 100644 --- a/modules/audio_coding/codecs/opus/audio_encoder_opus.h +++ b/modules/audio_coding/codecs/opus/audio_encoder_opus.h @@ -104,8 +104,6 @@ class AudioEncoderOpusImpl final : public AudioEncoder { void DisableAudioNetworkAdaptor() override; void OnReceivedUplinkPacketLossFraction( float uplink_packet_loss_fraction) override; - void OnReceivedUplinkRecoverablePacketLossFraction( - float uplink_recoverable_packet_loss_fraction) override; void OnReceivedUplinkBandwidth( int target_audio_bitrate_bps, absl::optional bwe_period_ms) override; diff --git a/modules/audio_coding/codecs/red/audio_encoder_copy_red.cc b/modules/audio_coding/codecs/red/audio_encoder_copy_red.cc index a0db045977..05aaca17b9 100644 --- a/modules/audio_coding/codecs/red/audio_encoder_copy_red.cc +++ b/modules/audio_coding/codecs/red/audio_encoder_copy_red.cc @@ -125,12 +125,6 @@ void AudioEncoderCopyRed::OnReceivedUplinkPacketLossFraction( uplink_packet_loss_fraction); } -void AudioEncoderCopyRed::OnReceivedUplinkRecoverablePacketLossFraction( - float uplink_recoverable_packet_loss_fraction) { - speech_encoder_->OnReceivedUplinkRecoverablePacketLossFraction( - uplink_recoverable_packet_loss_fraction); -} - void AudioEncoderCopyRed::OnReceivedUplinkBandwidth( int target_audio_bitrate_bps, absl::optional bwe_period_ms) { diff --git a/modules/audio_coding/codecs/red/audio_encoder_copy_red.h b/modules/audio_coding/codecs/red/audio_encoder_copy_red.h index 448df2756f..2dc13dd405 100644 --- a/modules/audio_coding/codecs/red/audio_encoder_copy_red.h +++ b/modules/audio_coding/codecs/red/audio_encoder_copy_red.h @@ -57,8 +57,6 @@ class AudioEncoderCopyRed final : public AudioEncoder { override; void OnReceivedUplinkPacketLossFraction( float uplink_packet_loss_fraction) override; - void OnReceivedUplinkRecoverablePacketLossFraction( - float uplink_recoverable_packet_loss_fraction) override; void OnReceivedUplinkBandwidth( int target_audio_bitrate_bps, absl::optional bwe_period_ms) override; diff --git a/test/fuzzers/BUILD.gn b/test/fuzzers/BUILD.gn index d6dbf5158a..9bd8cef5da 100644 --- a/test/fuzzers/BUILD.gn +++ b/test/fuzzers/BUILD.gn @@ -457,17 +457,6 @@ webrtc_fuzzer_test("pseudotcp_parser_fuzzer") { ] } -webrtc_fuzzer_test("transport_feedback_packet_loss_tracker_fuzzer") { - sources = [ - "transport_feedback_packet_loss_tracker_fuzzer.cc", - ] - deps = [ - "../../api:array_view", - "../../audio", - "../../modules/rtp_rtcp:rtp_rtcp_format", - "../../rtc_base:rtc_base_approved", - ] -} rtc_library("audio_processing_fuzzer_helper") { sources = [ "audio_processing_fuzzer_helper.cc", diff --git a/test/fuzzers/transport_feedback_packet_loss_tracker_fuzzer.cc b/test/fuzzers/transport_feedback_packet_loss_tracker_fuzzer.cc deleted file mode 100644 index 2168d219f9..0000000000 --- a/test/fuzzers/transport_feedback_packet_loss_tracker_fuzzer.cc +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include - -#include "api/array_view.h" -#include "audio/transport_feedback_packet_loss_tracker.h" -#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" -#include "modules/rtp_rtcp/source/byte_io.h" -#include "modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h" - -namespace webrtc { - -namespace { - -template -T FuzzInput(const uint8_t** data, size_t* size) { - RTC_CHECK_GE(*size, sizeof(T)); - T rc = ByteReader::ReadBigEndian(*data); - *data += sizeof(T); - *size -= sizeof(T); - return rc; -} - -size_t FuzzInRange(const uint8_t** data, - size_t* size, - size_t lower, - size_t upper) { - // Achieve a close-to-uniform distribution. - RTC_CHECK_LE(lower, upper); - RTC_CHECK_LT(upper - lower, 1 << (8 * sizeof(uint16_t))); - const size_t range = upper - lower; - const uint16_t fuzzed = FuzzInput(data, size); - const size_t offset = (static_cast(fuzzed) / 0x10000) * (range + 1); - RTC_CHECK_LE(offset, range); // (fuzzed <= 0xffff) -> (offset < range + 1) - return lower + offset; -} - -class TransportFeedbackGenerator { - public: - explicit TransportFeedbackGenerator(const uint8_t** data, size_t* size) - : data_(data), size_(size) {} - - bool GetNextTransportFeedbackVector( - std::vector* feedback_vector) { - RTC_CHECK(feedback_vector->empty()); - - uint16_t remaining_packets = 0; - if (!ReadData(&remaining_packets)) { - return false; - } - - if (remaining_packets == 0) { - return true; - } - - uint16_t seq_num; - if (!ReadData(&seq_num)) { // Fuzz base sequence number. - return false; - } - - while (remaining_packets > 0) { - uint8_t status_byte = 0; - if (!ReadData(&status_byte)) { - return false; - } - // Each status byte contains 8 statuses. - for (size_t i = 0; i < 8 && remaining_packets > 0; ++i) { - // Any positive integer signals reception. kNotReceived signals loss. - // Other values are just illegal. - constexpr int64_t kArrivalTimeMs = 1234; - - const bool received = (status_byte & (0x01 << i)); - feedback_vector->emplace_back(PacketFeedback( - received ? kArrivalTimeMs : PacketFeedback::kNotReceived, - seq_num++)); - --remaining_packets; - } - } - - return true; - } - - private: - template - bool ReadData(T* value) { - if (*size_ < sizeof(T)) { - return false; - } else { - *value = FuzzInput(data_, size_); - return true; - } - } - - const uint8_t** data_; - size_t* size_; -}; - -bool Setup(const uint8_t** data, - size_t* size, - std::unique_ptr* tracker) { - if (*size < 3 * sizeof(uint16_t)) { - return false; - } - - constexpr size_t kSeqNumHalf = 0x8000u; - - const int64_t max_window_size_ms = FuzzInRange(data, size, 1, 1 << 16); - const size_t plr_min_num_packets = FuzzInRange(data, size, 1, kSeqNumHalf); - const size_t rplr_min_num_pairs = FuzzInRange(data, size, 1, kSeqNumHalf - 1); - - tracker->reset(new TransportFeedbackPacketLossTracker( - max_window_size_ms, plr_min_num_packets, rplr_min_num_pairs)); - - return true; -} - -bool FuzzSequenceNumberDelta(const uint8_t** data, - size_t* size, - uint16_t* delta) { - // Fuzz with a higher likelihood for immediately consecutive pairs - // than you would by just fuzzing 1-256. - // Note: Values higher than 256 still possible, but that would be in a new - // packet-sending block. - // * Fuzzed value in [0 : 127] (50% chance) -> delta is 1. - // * Fuzzed value in [128 : 255] (50% chance) -> delta in range [2 : 129]. - if (*size < sizeof(uint8_t)) { - return false; - } - uint8_t fuzzed = FuzzInput(data, size); - *delta = (fuzzed < 128) ? 1 : (fuzzed - 128 + 2); - return true; -} - -bool FuzzClockAdvancement(const uint8_t** data, - size_t* size, - int64_t* time_ms) { - // Fuzzing 64-bit worth of delta would be extreme overkill, as 32-bit is - // already ~49 days long. We'll fuzz deltas up to a smaller value, and this - // way also guarantee that wrap-around is impossible, as in real life. - - // Higher likelihood for more likely cases: - // 5% chance of delta = 0. - // 20% chance of delta in range [1 : 10] (uniformly distributed) - // 55% chance of delta in range [11 : 500] (uniformly distributed) - // 20% chance of delta in range [501 : 10000] (uniformly distributed) - struct ProbabilityDistribution { - float probability; - size_t lower; - size_t higher; - }; - constexpr ProbabilityDistribution clock_probability_distribution[] = { - {0.05, 0, 0}, {0.20, 1, 10}, {0.55, 11, 500}, {0.20, 501, 10000}}; - - if (*size < sizeof(uint8_t)) { - return false; - } - const float fuzzed = FuzzInput(data, size) / 256.0f; - - float cumulative_probability = 0; - for (const auto& dist : clock_probability_distribution) { - cumulative_probability += dist.probability; - if (fuzzed < cumulative_probability) { - if (dist.lower == dist.higher) { - *time_ms += dist.lower; - return true; - } else if (*size < sizeof(uint16_t)) { - return false; - } else { - *time_ms += FuzzInRange(data, size, dist.lower, dist.higher); - return true; - } - } - } - - RTC_NOTREACHED(); - return false; -} - -bool FuzzPacketSendBlock( - std::unique_ptr& tracker, - const uint8_t** data, - size_t* size, - int64_t* time_ms) { - // We want to test with block lengths between 1 and 2^16, inclusive. - if (*size < sizeof(uint8_t)) { - return false; - } - size_t packet_block_len = 1 + FuzzInput(data, size); - - // First sent sequence number uniformly selected. - if (*size < sizeof(uint16_t)) { - return false; - } - uint16_t seq_num = FuzzInput(data, size); - tracker->OnPacketAdded(seq_num, *time_ms); - tracker->Validate(); - - bool may_continue = FuzzClockAdvancement(data, size, time_ms); - if (!may_continue) { - return false; - } - - for (size_t i = 1; i < packet_block_len; i++) { - uint16_t delta; - may_continue = FuzzSequenceNumberDelta(data, size, &delta); - if (!may_continue) - return false; - may_continue = FuzzClockAdvancement(data, size, time_ms); - if (!may_continue) - return false; - seq_num += delta; - tracker->OnPacketAdded(seq_num, *time_ms); - tracker->Validate(); - } - - return true; -} - -bool FuzzTransportFeedbackBlock( - std::unique_ptr& tracker, - const uint8_t** data, - size_t* size) { - // Fuzz the number of back-to-back feedbacks. At least one, or this would - // be meaningless - we'd go straight back to fuzzing another packet - // transmission block. - if (*size < sizeof(uint8_t)) { - return false; - } - - size_t feedbacks_num = 1 + (FuzzInput(data, size) & 0x3f); - TransportFeedbackGenerator feedback_generator(data, size); - - for (size_t i = 0; i < feedbacks_num; i++) { - std::vector feedback_vector; - bool may_continue = - feedback_generator.GetNextTransportFeedbackVector(&feedback_vector); - if (!may_continue) { - return false; - } - tracker->OnPacketFeedbackVector(feedback_vector); - tracker->Validate(); - } - - return true; -} - -} // namespace - -void FuzzOneInput(const uint8_t* data, size_t size) { - std::unique_ptr tracker; - bool may_continue; - - may_continue = Setup(&data, &size, &tracker); - - // We never expect this to wrap around, so it makes sense to just start with - // a sane value, and keep on incrementing by a fuzzed delta. - if (size < sizeof(uint32_t)) { - return; - } - int64_t time_ms = FuzzInput(&data, &size); - - while (may_continue) { - may_continue = FuzzPacketSendBlock(tracker, &data, &size, &time_ms); - if (!may_continue) { - return; - } - may_continue = FuzzTransportFeedbackBlock(tracker, &data, &size); - } -} - -} // namespace webrtc