|  | 
 | /* | 
 |  *  Copyright (c) 2024 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/remote_bitrate_estimator/congestion_control_feedback_tracker.h" | 
 |  | 
 | #include <cstdint> | 
 | #include <tuple> | 
 | #include <vector> | 
 |  | 
 | #include "absl/algorithm/container.h" | 
 | #include "api/units/time_delta.h" | 
 | #include "api/units/timestamp.h" | 
 | #include "modules/rtp_rtcp/source/rtcp_packet/congestion_control_feedback.h" | 
 | #include "modules/rtp_rtcp/source/rtp_packet_received.h" | 
 | #include "rtc_base/checks.h" | 
 | #include "rtc_base/logging.h" | 
 | #include "rtc_base/network/ecn_marking.h" | 
 |  | 
 | namespace webrtc { | 
 |  | 
 | constexpr int kMaxPacketsPerSsrc = 16384; | 
 |  | 
 | void CongestionControlFeedbackTracker::ReceivedPacket( | 
 |     const RtpPacketReceived& packet) { | 
 |   if (packets_.size() > kMaxPacketsPerSsrc) { | 
 |     RTC_LOG(LS_VERBOSE) | 
 |         << "Unexpected number of packets without sending reports:" | 
 |         << packets_.size(); | 
 |     return; | 
 |   } | 
 |   int64_t unwrapped_sequence_number = | 
 |       unwrapper_.Unwrap(packet.SequenceNumber()); | 
 |   if (last_sequence_number_in_feedback_ && | 
 |       unwrapped_sequence_number < *last_sequence_number_in_feedback_ + 1) { | 
 |     RTC_LOG(LS_WARNING) | 
 |         << "Received packet unorderered between feeedback. SSRC: " | 
 |         << packet.Ssrc() << " Seq: " << packet.SequenceNumber() | 
 |         << " last feedback: " | 
 |         << static_cast<uint16_t>(*last_sequence_number_in_feedback_); | 
 |     // TODO: bugs.webrtc.org/374550342 - According to spec, the old packets | 
 |     // should be reported again. But at the moment, we dont store history of | 
 |     // packet we already reported and thus, they will be reported as lost. | 
 |     // Note that this is likely not a problem in webrtc since the packets will | 
 |     // also be removed from the send history when they are first reported as | 
 |     // received. | 
 |     last_sequence_number_in_feedback_ = unwrapped_sequence_number - 1; | 
 |   } | 
 |   packets_.push_back({.ssrc = packet.Ssrc(), | 
 |                       .unwrapped_sequence_number = unwrapped_sequence_number, | 
 |                       .arrival_time = packet.arrival_time(), | 
 |                       .ecn = packet.ecn()}); | 
 | } | 
 |  | 
 | void CongestionControlFeedbackTracker::AddPacketsToFeedback( | 
 |     Timestamp feedback_time, | 
 |     std::vector<rtcp::CongestionControlFeedback::PacketInfo>& packet_feedback) { | 
 |   if (packets_.empty()) { | 
 |     return; | 
 |   } | 
 |   absl::c_sort(packets_, [](const PacketInfo& a, const PacketInfo& b) { | 
 |     return std::tie(a.unwrapped_sequence_number, a.arrival_time) < | 
 |            std::tie(b.unwrapped_sequence_number, b.arrival_time); | 
 |   }); | 
 |   if (!last_sequence_number_in_feedback_) { | 
 |     last_sequence_number_in_feedback_ = | 
 |         packets_.front().unwrapped_sequence_number - 1; | 
 |   } | 
 |  | 
 |   auto packet_it = packets_.begin(); | 
 |   uint32_t ssrc = packet_it->ssrc; | 
 |   for (int64_t sequence_number = *last_sequence_number_in_feedback_ + 1; | 
 |        sequence_number <= packets_.back().unwrapped_sequence_number && | 
 |        sequence_number <= | 
 |            *last_sequence_number_in_feedback_ + kMaxPacketsPerSsrc; | 
 |        ++sequence_number) { | 
 |     RTC_DCHECK(packet_it != packets_.end()); | 
 |     RTC_DCHECK_EQ(ssrc, packet_it->ssrc); | 
 |  | 
 |     rtc::EcnMarking ecn = rtc::EcnMarking::kNotEct; | 
 |     TimeDelta arrival_time_offset = TimeDelta::MinusInfinity(); | 
 |  | 
 |     if (sequence_number == packet_it->unwrapped_sequence_number) { | 
 |       arrival_time_offset = feedback_time - packet_it->arrival_time; | 
 |       ecn = packet_it->ecn; | 
 |       ++packet_it; | 
 |       while (packet_it != packets_.end() && | 
 |              packet_it->unwrapped_sequence_number == sequence_number) { | 
 |         // According to RFC 8888: | 
 |         // If duplicate copies of a particular RTP packet are received, then the | 
 |         // arrival time of the first copy to arrive MUST be reported. If any of | 
 |         // the copies of the duplicated packet are ECN-CE marked, then an ECN-CE | 
 |         // mark MUST be reported for that packet; otherwise, the ECN mark of the | 
 |         // first copy to arrive is reported. | 
 |         if (packet_it->ecn == rtc::EcnMarking::kCe) { | 
 |           ecn = rtc::EcnMarking::kCe; | 
 |         } | 
 |         RTC_LOG(LS_WARNING) << "Received duplicate packet ssrc:" << ssrc | 
 |                             << " seq:" << static_cast<uint16_t>(sequence_number) | 
 |                             << " ecn: " << static_cast<int>(ecn); | 
 |         ++packet_it; | 
 |       } | 
 |     }  // else - the packet has not been received yet. | 
 |     packet_feedback.push_back( | 
 |         {.ssrc = ssrc, | 
 |          .sequence_number = static_cast<uint16_t>(sequence_number), | 
 |          .arrival_time_offset = arrival_time_offset, | 
 |          .ecn = ecn}); | 
 |   } | 
 |   last_sequence_number_in_feedback_ = packets_.back().unwrapped_sequence_number; | 
 |   packets_.clear(); | 
 | } | 
 |  | 
 | }  // namespace webrtc |