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..3d917ed7c8ff97e94c933cdb6d4ae2a2f21036e5 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,9 @@ |
namespace webrtc { |
+// Only return the contribuing sources in the last 10 seconds. |
+static const int64_t kContributingSourcesTimeoutMs = 10000; |
+ |
using RtpUtility::Payload; |
RtpReceiver* RtpReceiver::CreateVideoReceiver( |
@@ -53,11 +59,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), |
@@ -69,7 +74,9 @@ RtpReceiverImpl::RtpReceiverImpl( |
current_remote_csrc_(), |
last_received_timestamp_(0), |
last_received_frame_time_ms_(-1), |
- last_received_sequence_number_(0) { |
+ last_received_sequence_number_(0), |
+ current_buffer_index_(0), |
+ current_buffer_size_(0) { |
assert(incoming_messages_callback); |
memset(current_remote_csrc_, 0, sizeof(current_remote_csrc_)); |
@@ -160,6 +167,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 +212,42 @@ TelephoneEventHandler* RtpReceiverImpl::GetTelephoneEventHandler() { |
return rtp_media_receiver_->GetTelephoneEventHandler(); |
} |
+const std::vector<RtpContributingSource>& |
+RtpReceiverImpl::GetContributingSources() { |
+ contributing_sources_.clear(); |
+ std::set<uint32_t> selected_sources_set; |
+ int64_t now = clock_->TimeInMilliseconds(); |
+ |
+ { |
+ rtc::CritScope lock(&critical_section_rtp_receiver_); |
+ |
+ for (size_t i = 1; i <= current_buffer_size_; ++i) { |
+ // Iterate the buffer in reverse order. |
+ size_t index = |
+ (current_buffer_index_ + kContributingSourcesBufferSize - i) % |
+ kContributingSourcesBufferSize; |
+ RtpContributingSource& contributing_source = |
+ contributing_sources_buffer_[index]; |
+ // Stop iterating when the contributing source object is out of date since |
+ // the buffer is ordered by the timestamp. |
+ if (now - contributing_source.timestamp > kContributingSourcesTimeoutMs) |
+ break; |
+ // Return the latest timestamp for a given SSRC and skip the duplicated |
+ // ones. |
+ if (selected_sources_set.find(contributing_source.source) == |
+ selected_sources_set.end()) { |
+ selected_sources_set.insert(contributing_source.source); |
+ contributing_sources_.push_back(contributing_source); |
+ } |
+ } |
+ |
+ // Add the contributing source using the SSRC. |
+ contributing_sources_.push_back(ssrc_source_); |
+ } // End critsect. |
+ |
+ return contributing_sources_; |
+} |
+ |
bool RtpReceiverImpl::Timestamp(uint32_t* timestamp) const { |
rtc::CritScope lock(&critical_section_rtp_receiver_); |
if (!HaveReceivedFrame()) |
@@ -461,4 +506,32 @@ 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) { |
+ contributing_sources_buffer_[current_buffer_index_].timestamp = now; |
+ contributing_sources_buffer_[current_buffer_index_].source = |
+ current_remote_csrc_[i]; |
+ current_buffer_index_ = |
+ (current_buffer_index_ + 1) % kContributingSourcesBufferSize; |
+ |
+ if (current_buffer_size_ < kContributingSourcesBufferSize) { |
+ ++current_buffer_size_; |
+ } |
+ } |
+ |
+ // If the SSRC is changed and the old SSRC has been kept for more than |
+ // |kContributingSourcesTimeoutMs| or this is the first RTP packet, update |
+ // both the ssrc and timestamp. |
+ // If the SSRC isn't changed, just update the timestamp. |
+ if ((now - ssrc_source_.timestamp) > kContributingSourcesTimeoutMs || |
+ ssrc_source_.source == 0) { |
+ ssrc_source_.timestamp = now; |
+ ssrc_source_.source = ssrc_; |
+ } else if (ssrc_ == ssrc_source_.source) { |
+ ssrc_source_.timestamp = now; |
+ } |
+} |
+ |
} // namespace webrtc |