 Chromium Code Reviews
 Chromium Code Reviews Issue 2770233003:
  Implemented the GetSources() in native code.  (Closed)
    
  
    Issue 2770233003:
  Implemented the GetSources() in native code.  (Closed) 
  | 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..fe4e837dc10bae5145636a97fff9814582c496f5 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" | 
| @@ -25,6 +28,9 @@ namespace webrtc { | 
| using RtpUtility::Payload; | 
| +// Only return the sources in the last 10 seconds. | 
| +const int64_t kGetSourcesTimeoutMs = 10000; | 
| + | 
| RtpReceiver* RtpReceiver::CreateVideoReceiver( | 
| Clock* clock, | 
| RtpData* incoming_payload_callback, | 
| @@ -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), | 
| @@ -160,6 +165,8 @@ bool RtpReceiverImpl::IncomingRtpPacket( | 
| webrtc_rtp_header.header = rtp_header; | 
| CheckCSRC(webrtc_rtp_header); | 
| + UpdateSources(); | 
| + | 
| size_t payload_data_length = payload_length - rtp_header.paddingLength; | 
| bool is_first_packet_in_frame = false; | 
| @@ -203,6 +210,45 @@ TelephoneEventHandler* RtpReceiverImpl::GetTelephoneEventHandler() { | 
| return rtp_media_receiver_->GetTelephoneEventHandler(); | 
| } | 
| +std::vector<RtpSource> RtpReceiverImpl::GetSources() const { | 
| + int64_t now = clock_->TimeInMilliseconds(); | 
| + std::vector<RtpSource> sources; | 
| 
philipel
2017/04/06 14:33:34
I think it would be cleaner if this was an std::se
 
Zhi Huang
2017/04/06 22:30:25
But then we'll need an additional compare struct f
 
philipel
2017/04/07 08:44:07
Acknowledged.
 | 
| + | 
| + { | 
| + rtc::CritScope lock(&critical_section_rtp_receiver_); | 
| + | 
| + RTC_DCHECK(std::is_sorted(ssrc_sources_.begin(), ssrc_sources_.end(), | 
| + [](const RtpSource& lhs, const RtpSource& rhs) { | 
| + return lhs.timestamp_ms() < rhs.timestamp_ms(); | 
| + })); | 
| + RTC_DCHECK(std::is_sorted(csrc_sources_.begin(), csrc_sources_.end(), | 
| + [](const RtpSource& lhs, const RtpSource& rhs) { | 
| + return lhs.timestamp_ms() < rhs.timestamp_ms(); | 
| + })); | 
| + | 
| + std::set<uint32_t> selected_ssrcs; | 
| + for (auto rit = ssrc_sources_.rbegin(); rit != ssrc_sources_.rend(); | 
| + ++rit) { | 
| + if ((now - rit->timestamp_ms()) > kGetSourcesTimeoutMs) { | 
| + break; | 
| + } | 
| + if (selected_ssrcs.insert(rit->source_id()).second) { | 
| + sources.push_back(*rit); | 
| + } | 
| + } | 
| + | 
| + for (auto rit = csrc_sources_.rbegin(); rit != csrc_sources_.rend(); | 
| + ++rit) { | 
| + if ((now - rit->timestamp_ms()) > kGetSourcesTimeoutMs) { | 
| + break; | 
| + } | 
| + sources.push_back(*rit); | 
| + } | 
| + } // End critsect. | 
| + | 
| + return sources; | 
| +} | 
| + | 
| bool RtpReceiverImpl::Timestamp(uint32_t* timestamp) const { | 
| rtc::CritScope lock(&critical_section_rtp_receiver_); | 
| if (!HaveReceivedFrame()) | 
| @@ -461,4 +507,56 @@ void RtpReceiverImpl::CheckCSRC(const WebRtcRTPHeader& rtp_header) { | 
| } | 
| } | 
| +void RtpReceiverImpl::UpdateSources() { | 
| + rtc::CritScope lock(&critical_section_rtp_receiver_); | 
| + int64_t now = clock_->TimeInMilliseconds(); | 
| 
philipel
2017/04/06 14:33:34
now_ms
 
Zhi Huang
2017/04/06 22:30:24
Done.
 | 
| + | 
| + for (size_t i = 0; i < num_csrcs_; ++i) { | 
| + auto map_it = iterator_by_csrc_.find(current_remote_csrc_[i]); | 
| + if (map_it == iterator_by_csrc_.end()) { | 
| + // If it is a new CSRC, append a new object to the end of the list. | 
| + csrc_sources_.emplace_back(now, current_remote_csrc_[i], | 
| + RtpSourceType::CSRC); | 
| + } else { | 
| + // If it is an existing CSRC, move the object to the end of the list. | 
| + map_it->second->update_timestamp_ms(now); | 
| + csrc_sources_.splice(csrc_sources_.end(), csrc_sources_, map_it->second); | 
| + } | 
| + // Update the unordered_map. | 
| + iterator_by_csrc_[current_remote_csrc_[i]] = std::prev(csrc_sources_.end()); | 
| 
philipel
2017/04/06 14:33:34
std::prev(csrc_sources_.end()) --> csrc_sources_.r
 
Zhi Huang
2017/04/06 22:30:25
The value of the map is not reverse_iterator since
 
philipel
2017/04/07 08:44:07
Ah... ofc :)
 | 
| + } | 
| + | 
| + // If this is the first packet or the SSRC is changed, insert a new | 
| + // contributing source that uses the SSRC. | 
| + if (ssrc_sources_.size() == 0 || | 
| 
philipel
2017/04/06 14:33:34
ssrc_sources_.empty()
 
Zhi Huang
2017/04/06 22:30:24
Done.
 | 
| + std::prev(ssrc_sources_.end())->source_id() != ssrc_) { | 
| 
philipel
2017/04/06 14:33:34
std::prev(ssrc_sources_.end()) --> ssrc_sources_.r
 
Zhi Huang
2017/04/06 22:30:25
This is a good one!
 | 
| + ssrc_sources_.emplace_back(now, ssrc_, RtpSourceType::SSRC); | 
| + } else { | 
| + std::prev(ssrc_sources_.end())->update_timestamp_ms(now); | 
| 
philipel
2017/04/06 14:33:34
rbegin()
 
Zhi Huang
2017/04/06 22:30:25
Done.
 | 
| + } | 
| + | 
| + RemoveOutdatedSources(now); | 
| +} | 
| + | 
| +void RtpReceiverImpl::RemoveOutdatedSources(int64_t now) { | 
| + std::list<RtpSource>::iterator it; | 
| + for (it = csrc_sources_.begin(); it != csrc_sources_.end();) { | 
| + if ((now - it->timestamp_ms()) <= kGetSourcesTimeoutMs) { | 
| + break; | 
| + } | 
| + iterator_by_csrc_.erase(it->source_id()); | 
| + ++it; | 
| 
hbos
2017/04/06 08:17:16
nit: now that every iteration ends with ++it you c
 
Zhi Huang
2017/04/06 22:30:25
Done.
 | 
| + } | 
| + csrc_sources_.erase(csrc_sources_.begin(), it); | 
| + | 
| + std::vector<RtpSource>::iterator vec_it; | 
| + for (vec_it = ssrc_sources_.begin(); vec_it != ssrc_sources_.end(); | 
| + ++vec_it) { | 
| + if ((now - vec_it->timestamp_ms()) <= kGetSourcesTimeoutMs) { | 
| + break; | 
| + } | 
| + } | 
| + ssrc_sources_.erase(ssrc_sources_.begin(), vec_it); | 
| +} | 
| + | 
| } // namespace webrtc |