Chromium Code Reviews| 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; |
|
the sun
2017/04/04 21:09:58
Should the SSRCs go first in the result, or doesn'
Zhi Huang
2017/04/05 04:16:03
I don't think this matters but it feels that the l
|
| + 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. |
|
the sun
2017/04/04 21:09:58
nit: move comment inside if (..) {
Zhi Huang
2017/04/05 04:16:04
Done.
|
| + if (map_it == iterator_by_csrc_.end()) { |
| + RtpContributingSource contributing_source; |
| + contributing_source.set_timestamp(now); |
|
the sun
2017/04/04 21:09:58
Make these arguments to ctor instead, to avoid the
Zhi Huang
2017/04/05 04:16:04
Done.
|
| + 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()); |
|
the sun
2017/04/04 21:09:57
avoid the named temp and make it a single statemen
Zhi Huang
2017/04/05 04:16:04
Done.
|
| + 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() > |
|
the sun
2017/04/04 21:09:58
nit: add () around the addition, to make it clear
Zhi Huang
2017/04/05 04:16:04
Done.
|
| + 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_) { |
|
the sun
2017/04/04 21:09:58
std::prev(ssrc_contributing_sources_.end())->ssrc(
Zhi Huang
2017/04/05 04:16:04
Done.
|
| + RtpContributingSource ssrc_source; |
| + ssrc_source.set_timestamp(now); |
| + ssrc_source.set_ssrc(ssrc_); |
| + ssrc_source_list_.push_back(ssrc_source); |
|
the sun
2017/04/04 21:09:58
emplace_back
Zhi Huang
2017/04/05 04:16:04
Done.
|
| + } 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) { |
|
the sun
2017/04/04 21:09:58
Use it->... instead of (*it). (here and elsewhere)
Zhi Huang
2017/04/05 04:16:04
Done.
|
| + 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); |
|
the sun
2017/04/04 21:09:58
This invalidates 'it' so the ++it in the loop will
Zhi Huang
2017/04/05 04:16:04
Thanks for catching this. I'll add a test to cover
|
| + } |
| +} |
| + |
| } // namespace webrtc |