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()19TransportFeedbackDemuxer::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)25void 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)36void 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)46void 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)63void 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