xref: /aosp_15_r20/external/webrtc/modules/congestion_controller/rtp/transport_feedback_demuxer.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 #include "modules/congestion_controller/rtp/transport_feedback_demuxer.h"
11 #include "absl/algorithm/container.h"
12 #include "modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
13 
14 namespace webrtc {
15 namespace {
16 static const size_t kMaxPacketsInHistory = 5000;
17 }
18 
TransportFeedbackDemuxer()19 TransportFeedbackDemuxer::TransportFeedbackDemuxer() {
20   // In case the construction thread is different from where the registration
21   // and callbacks occur, detach from the construction thread.
22   observer_checker_.Detach();
23 }
24 
RegisterStreamFeedbackObserver(std::vector<uint32_t> ssrcs,StreamFeedbackObserver * observer)25 void TransportFeedbackDemuxer::RegisterStreamFeedbackObserver(
26     std::vector<uint32_t> ssrcs,
27     StreamFeedbackObserver* observer) {
28   RTC_DCHECK_RUN_ON(&observer_checker_);
29   RTC_DCHECK(observer);
30   RTC_DCHECK(absl::c_find_if(observers_, [=](const auto& pair) {
31                return pair.second == observer;
32              }) == observers_.end());
33   observers_.push_back({ssrcs, observer});
34 }
35 
DeRegisterStreamFeedbackObserver(StreamFeedbackObserver * observer)36 void TransportFeedbackDemuxer::DeRegisterStreamFeedbackObserver(
37     StreamFeedbackObserver* observer) {
38   RTC_DCHECK_RUN_ON(&observer_checker_);
39   RTC_DCHECK(observer);
40   const auto it = absl::c_find_if(
41       observers_, [=](const auto& pair) { return pair.second == observer; });
42   RTC_DCHECK(it != observers_.end());
43   observers_.erase(it);
44 }
45 
AddPacket(const RtpPacketSendInfo & packet_info)46 void TransportFeedbackDemuxer::AddPacket(const RtpPacketSendInfo& packet_info) {
47   RTC_DCHECK_RUN_ON(&observer_checker_);
48 
49   StreamFeedbackObserver::StreamPacketInfo info;
50   info.ssrc = packet_info.media_ssrc;
51   info.rtp_sequence_number = packet_info.rtp_sequence_number;
52   info.received = false;
53   info.is_retransmission =
54       packet_info.packet_type == RtpPacketMediaType::kRetransmission;
55   history_.insert(
56       {seq_num_unwrapper_.Unwrap(packet_info.transport_sequence_number), info});
57 
58   while (history_.size() > kMaxPacketsInHistory) {
59     history_.erase(history_.begin());
60   }
61 }
62 
OnTransportFeedback(const rtcp::TransportFeedback & feedback)63 void TransportFeedbackDemuxer::OnTransportFeedback(
64     const rtcp::TransportFeedback& feedback) {
65   RTC_DCHECK_RUN_ON(&observer_checker_);
66 
67   std::vector<StreamFeedbackObserver::StreamPacketInfo> stream_feedbacks;
68   for (const auto& packet : feedback.GetAllPackets()) {
69     int64_t seq_num =
70         seq_num_unwrapper_.UnwrapWithoutUpdate(packet.sequence_number());
71     auto it = history_.find(seq_num);
72     if (it != history_.end()) {
73       auto packet_info = it->second;
74       packet_info.received = packet.received();
75       stream_feedbacks.push_back(std::move(packet_info));
76       if (packet.received())
77         history_.erase(it);
78     }
79   }
80 
81   for (auto& observer : observers_) {
82     std::vector<StreamFeedbackObserver::StreamPacketInfo> selected_feedback;
83     for (const auto& packet_info : stream_feedbacks) {
84       if (absl::c_count(observer.first, packet_info.ssrc) > 0) {
85         selected_feedback.push_back(packet_info);
86       }
87     }
88     if (!selected_feedback.empty()) {
89       observer.second->OnPacketFeedbackVector(std::move(selected_feedback));
90     }
91   }
92 }
93 
94 }  // namespace webrtc
95