Index: webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.cc |
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.cc b/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.cc |
index 79e43ef073536d17e58d6f7b8200e0a7d79be743..8f228954fb71a6cefc380237d8b415e338ea5a2d 100644 |
--- a/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.cc |
+++ b/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.cc |
@@ -15,6 +15,9 @@ |
#include <stdlib.h> |
#include <string.h> |
+#include <set> |
+#include <vector> |
+ |
#include "webrtc/base/logging.h" |
#include "webrtc/common_types.h" |
#include "webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h" |
@@ -23,6 +26,12 @@ |
namespace webrtc { |
+// Only return the contribuing sources in the last 10 seconds. |
+static const int64_t kContributingSourcesTimeoutMs = 10000; |
+ |
+// The maximum size of the contributing sources lists. |
+static const int kMaxContributingSourceListsSize = 100; |
+ |
using RtpUtility::Payload; |
RtpReceiver* RtpReceiver::CreateVideoReceiver( |
@@ -53,11 +62,10 @@ RtpReceiver* RtpReceiver::CreateAudioReceiver( |
RTPReceiverStrategy::CreateAudioStrategy(incoming_payload_callback)); |
} |
-RtpReceiverImpl::RtpReceiverImpl( |
- Clock* clock, |
- RtpFeedback* incoming_messages_callback, |
- RTPPayloadRegistry* rtp_payload_registry, |
- RTPReceiverStrategy* rtp_media_receiver) |
+RtpReceiverImpl::RtpReceiverImpl(Clock* clock, |
+ RtpFeedback* incoming_messages_callback, |
+ RTPPayloadRegistry* rtp_payload_registry, |
+ RTPReceiverStrategy* rtp_media_receiver) |
: clock_(clock), |
rtp_payload_registry_(rtp_payload_registry), |
rtp_media_receiver_(rtp_media_receiver), |
@@ -160,6 +168,8 @@ bool RtpReceiverImpl::IncomingRtpPacket( |
webrtc_rtp_header.header = rtp_header; |
CheckCSRC(webrtc_rtp_header); |
+ UpdateContributingSource(); |
+ |
size_t payload_data_length = payload_length - rtp_header.paddingLength; |
bool is_first_packet_in_frame = false; |
@@ -203,6 +213,38 @@ TelephoneEventHandler* RtpReceiverImpl::GetTelephoneEventHandler() { |
return rtp_media_receiver_->GetTelephoneEventHandler(); |
} |
+std::vector<RtpContributingSource> RtpReceiverImpl::GetContributingSources() { |
+ int64_t now = clock_->TimeInMilliseconds(); |
+ std::vector<RtpContributingSource> contributing_sources; |
+ |
+ { |
+ rtc::CritScope lock(&critical_section_rtp_receiver_); |
+ |
+ for (auto rit = csrc_source_list_.rbegin(); rit != csrc_source_list_.rend(); |
+ ++rit) { |
+ if (now - (*rit).timestamp() > kContributingSourcesTimeoutMs) { |
+ break; |
+ } |
+ contributing_sources.push_back(*rit); |
+ } |
+ |
+ // Add the contributing sources that use the SSRC. |
+ std::set<uint32_t> selected_ssrcs; |
+ for (auto rit = ssrc_source_list_.rbegin(); rit != ssrc_source_list_.rend(); |
+ ++rit) { |
+ if (now - (*rit).timestamp() > kContributingSourcesTimeoutMs) { |
+ break; |
+ } |
+ if (selected_ssrcs.find((*rit).ssrc()) == selected_ssrcs.end()) { |
+ selected_ssrcs.insert((*rit).ssrc()); |
+ contributing_sources.push_back(*rit); |
+ } |
+ } |
+ } // End critsect. |
+ |
+ return contributing_sources; |
+} |
+ |
bool RtpReceiverImpl::Timestamp(uint32_t* timestamp) const { |
rtc::CritScope lock(&critical_section_rtp_receiver_); |
if (!HaveReceivedFrame()) |
@@ -461,4 +503,67 @@ void RtpReceiverImpl::CheckCSRC(const WebRtcRTPHeader& rtp_header) { |
} |
} |
+void RtpReceiverImpl::UpdateContributingSource() { |
+ rtc::CritScope lock(&critical_section_rtp_receiver_); |
+ int64_t now = clock_->TimeInMilliseconds(); |
+ |
+ for (size_t i = 0; i < num_csrcs_; ++i) { |
+ auto map_it = iterator_by_csrc_.find(current_remote_csrc_[i]); |
+ // If it is a new CSRC, append a new object to the end of the list. |
+ if (map_it == iterator_by_csrc_.end()) { |
+ RtpContributingSource contributing_source; |
+ contributing_source.set_timestamp(now); |
+ contributing_source.set_csrc(current_remote_csrc_[i]); |
+ csrc_source_list_.push_back(contributing_source); |
+ } else { // Move the object to the end of the list. |
+ auto list_it = map_it->second; |
+ (*list_it).set_timestamp(now); |
+ (*list_it).set_csrc(current_remote_csrc_[i]); |
+ csrc_source_list_.splice(csrc_source_list_.end(), csrc_source_list_, |
+ list_it); |
+ } |
+ // Update the unordered_map. |
+ auto new_list_it = std::prev(csrc_source_list_.end()); |
+ iterator_by_csrc_[current_remote_csrc_[i]] = new_list_it; |
+ |
+ // Remove the out of date objects if the lists are too large. |
+ if (csrc_source_list_.size() + ssrc_source_list_.size() > |
+ kMaxContributingSourceListsSize) { |
+ UpdateSourceLists(now); |
+ } |
+ } |
+ |
+ // If this is the first packet or the SSRC is changed, insert a new |
+ // contributing source that uses the SSRC. |
+ if (ssrc_source_list_.size() == 0 || |
+ ssrc_source_list_[ssrc_source_list_.size() - 1].ssrc() != ssrc_) { |
+ RtpContributingSource ssrc_source; |
+ ssrc_source.set_timestamp(now); |
+ ssrc_source.set_ssrc(ssrc_); |
+ ssrc_source_list_.push_back(ssrc_source); |
+ } else { |
+ ssrc_source_list_[ssrc_source_list_.size() - 1].set_timestamp(now); |
+ } |
+} |
+ |
+// Update the lists and remove the out of date objects. |
+void RtpReceiverImpl::UpdateSourceLists(int64_t now) { |
+ for (auto it = csrc_source_list_.begin(); it != csrc_source_list_.end(); |
+ ++it) { |
+ if (now - (*it).timestamp() <= kContributingSourcesTimeoutMs) { |
+ break; |
+ } |
+ iterator_by_csrc_.erase((*it).source()); |
+ csrc_source_list_.erase(it); |
+ } |
+ |
+ for (auto it = ssrc_source_list_.begin(); it != ssrc_source_list_.end(); |
+ ++it) { |
+ if (now - (*it).timestamp() <= kContributingSourcesTimeoutMs) { |
+ break; |
+ } |
+ ssrc_source_list_.erase(it); |
+ } |
+} |
+ |
} // namespace webrtc |