| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| 11 #include "webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.h" | 11 #include "webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.h" |
| 12 | 12 |
| 13 #include <assert.h> | 13 #include <assert.h> |
| 14 #include <math.h> | 14 #include <math.h> |
| 15 #include <stdlib.h> | 15 #include <stdlib.h> |
| 16 #include <string.h> | 16 #include <string.h> |
| 17 | 17 |
| 18 #include <set> |
| 19 #include <vector> |
| 20 |
| 18 #include "webrtc/base/logging.h" | 21 #include "webrtc/base/logging.h" |
| 19 #include "webrtc/common_types.h" | 22 #include "webrtc/common_types.h" |
| 20 #include "webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h" | 23 #include "webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h" |
| 21 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" | 24 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" |
| 22 #include "webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.h" | 25 #include "webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.h" |
| 23 | 26 |
| 24 namespace webrtc { | 27 namespace webrtc { |
| 25 | 28 |
| 29 // Only return the contribuing sources in the last 10 seconds. |
| 30 static const int64_t kContributingSourcesTimeoutMs = 10000; |
| 31 |
| 26 using RtpUtility::Payload; | 32 using RtpUtility::Payload; |
| 27 | 33 |
| 28 RtpReceiver* RtpReceiver::CreateVideoReceiver( | 34 RtpReceiver* RtpReceiver::CreateVideoReceiver( |
| 29 Clock* clock, | 35 Clock* clock, |
| 30 RtpData* incoming_payload_callback, | 36 RtpData* incoming_payload_callback, |
| 31 RtpFeedback* incoming_messages_callback, | 37 RtpFeedback* incoming_messages_callback, |
| 32 RTPPayloadRegistry* rtp_payload_registry) { | 38 RTPPayloadRegistry* rtp_payload_registry) { |
| 33 if (!incoming_payload_callback) | 39 if (!incoming_payload_callback) |
| 34 incoming_payload_callback = NullObjectRtpData(); | 40 incoming_payload_callback = NullObjectRtpData(); |
| 35 if (!incoming_messages_callback) | 41 if (!incoming_messages_callback) |
| (...skipping 10 matching lines...) Expand all Loading... |
| 46 RTPPayloadRegistry* rtp_payload_registry) { | 52 RTPPayloadRegistry* rtp_payload_registry) { |
| 47 if (!incoming_payload_callback) | 53 if (!incoming_payload_callback) |
| 48 incoming_payload_callback = NullObjectRtpData(); | 54 incoming_payload_callback = NullObjectRtpData(); |
| 49 if (!incoming_messages_callback) | 55 if (!incoming_messages_callback) |
| 50 incoming_messages_callback = NullObjectRtpFeedback(); | 56 incoming_messages_callback = NullObjectRtpFeedback(); |
| 51 return new RtpReceiverImpl( | 57 return new RtpReceiverImpl( |
| 52 clock, incoming_messages_callback, rtp_payload_registry, | 58 clock, incoming_messages_callback, rtp_payload_registry, |
| 53 RTPReceiverStrategy::CreateAudioStrategy(incoming_payload_callback)); | 59 RTPReceiverStrategy::CreateAudioStrategy(incoming_payload_callback)); |
| 54 } | 60 } |
| 55 | 61 |
| 56 RtpReceiverImpl::RtpReceiverImpl( | 62 RtpReceiverImpl::RtpReceiverImpl(Clock* clock, |
| 57 Clock* clock, | 63 RtpFeedback* incoming_messages_callback, |
| 58 RtpFeedback* incoming_messages_callback, | 64 RTPPayloadRegistry* rtp_payload_registry, |
| 59 RTPPayloadRegistry* rtp_payload_registry, | 65 RTPReceiverStrategy* rtp_media_receiver) |
| 60 RTPReceiverStrategy* rtp_media_receiver) | |
| 61 : clock_(clock), | 66 : clock_(clock), |
| 62 rtp_payload_registry_(rtp_payload_registry), | 67 rtp_payload_registry_(rtp_payload_registry), |
| 63 rtp_media_receiver_(rtp_media_receiver), | 68 rtp_media_receiver_(rtp_media_receiver), |
| 64 cb_rtp_feedback_(incoming_messages_callback), | 69 cb_rtp_feedback_(incoming_messages_callback), |
| 65 last_receive_time_(0), | 70 last_receive_time_(0), |
| 66 last_received_payload_length_(0), | 71 last_received_payload_length_(0), |
| 67 ssrc_(0), | 72 ssrc_(0), |
| 68 num_csrcs_(0), | 73 num_csrcs_(0), |
| 69 current_remote_csrc_(), | 74 current_remote_csrc_(), |
| 70 last_received_timestamp_(0), | 75 last_received_timestamp_(0), |
| 71 last_received_frame_time_ms_(-1), | 76 last_received_frame_time_ms_(-1), |
| 72 last_received_sequence_number_(0) { | 77 last_received_sequence_number_(0), |
| 78 current_buffer_index_(0), |
| 79 current_buffer_size_(0) { |
| 73 assert(incoming_messages_callback); | 80 assert(incoming_messages_callback); |
| 74 | 81 |
| 75 memset(current_remote_csrc_, 0, sizeof(current_remote_csrc_)); | 82 memset(current_remote_csrc_, 0, sizeof(current_remote_csrc_)); |
| 76 } | 83 } |
| 77 | 84 |
| 78 RtpReceiverImpl::~RtpReceiverImpl() { | 85 RtpReceiverImpl::~RtpReceiverImpl() { |
| 79 for (int i = 0; i < num_csrcs_; ++i) { | 86 for (int i = 0; i < num_csrcs_; ++i) { |
| 80 cb_rtp_feedback_->OnIncomingCSRCChanged(current_remote_csrc_[i], false); | 87 cb_rtp_feedback_->OnIncomingCSRCChanged(current_remote_csrc_[i], false); |
| 81 } | 88 } |
| 82 } | 89 } |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 153 } | 160 } |
| 154 LOG(LS_WARNING) << "Receiving invalid payload type."; | 161 LOG(LS_WARNING) << "Receiving invalid payload type."; |
| 155 return false; | 162 return false; |
| 156 } | 163 } |
| 157 | 164 |
| 158 WebRtcRTPHeader webrtc_rtp_header; | 165 WebRtcRTPHeader webrtc_rtp_header; |
| 159 memset(&webrtc_rtp_header, 0, sizeof(webrtc_rtp_header)); | 166 memset(&webrtc_rtp_header, 0, sizeof(webrtc_rtp_header)); |
| 160 webrtc_rtp_header.header = rtp_header; | 167 webrtc_rtp_header.header = rtp_header; |
| 161 CheckCSRC(webrtc_rtp_header); | 168 CheckCSRC(webrtc_rtp_header); |
| 162 | 169 |
| 170 UpdateContributingSource(); |
| 171 |
| 163 size_t payload_data_length = payload_length - rtp_header.paddingLength; | 172 size_t payload_data_length = payload_length - rtp_header.paddingLength; |
| 164 | 173 |
| 165 bool is_first_packet_in_frame = false; | 174 bool is_first_packet_in_frame = false; |
| 166 { | 175 { |
| 167 rtc::CritScope lock(&critical_section_rtp_receiver_); | 176 rtc::CritScope lock(&critical_section_rtp_receiver_); |
| 168 if (HaveReceivedFrame()) { | 177 if (HaveReceivedFrame()) { |
| 169 is_first_packet_in_frame = | 178 is_first_packet_in_frame = |
| 170 last_received_sequence_number_ + 1 == rtp_header.sequenceNumber && | 179 last_received_sequence_number_ + 1 == rtp_header.sequenceNumber && |
| 171 last_received_timestamp_ != rtp_header.timestamp; | 180 last_received_timestamp_ != rtp_header.timestamp; |
| 172 } else { | 181 } else { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 196 last_received_sequence_number_ = rtp_header.sequenceNumber; | 205 last_received_sequence_number_ = rtp_header.sequenceNumber; |
| 197 } | 206 } |
| 198 } | 207 } |
| 199 return true; | 208 return true; |
| 200 } | 209 } |
| 201 | 210 |
| 202 TelephoneEventHandler* RtpReceiverImpl::GetTelephoneEventHandler() { | 211 TelephoneEventHandler* RtpReceiverImpl::GetTelephoneEventHandler() { |
| 203 return rtp_media_receiver_->GetTelephoneEventHandler(); | 212 return rtp_media_receiver_->GetTelephoneEventHandler(); |
| 204 } | 213 } |
| 205 | 214 |
| 215 const std::vector<RtpContributingSource>& |
| 216 RtpReceiverImpl::GetContributingSources() { |
| 217 contributing_sources_.clear(); |
| 218 std::set<uint32_t> selected_sources_set; |
| 219 int64_t now = clock_->TimeInMilliseconds(); |
| 220 |
| 221 { |
| 222 rtc::CritScope lock(&critical_section_rtp_receiver_); |
| 223 |
| 224 for (size_t i = 1; i <= current_buffer_size_; ++i) { |
| 225 // Iterate the buffer in reverse order. |
| 226 size_t index = |
| 227 (current_buffer_index_ + kContributingSourcesBufferSize - i) % |
| 228 kContributingSourcesBufferSize; |
| 229 RtpContributingSource& contributing_source = |
| 230 contributing_sources_buffer_[index]; |
| 231 // Stop iterating when the contributing source object is out of date since |
| 232 // the buffer is ordered by the timestamp. |
| 233 if (now - contributing_source.timestamp > kContributingSourcesTimeoutMs) |
| 234 break; |
| 235 // Return the latest timestamp for a given SSRC and skip the duplicated |
| 236 // ones. |
| 237 if (selected_sources_set.find(contributing_source.source) == |
| 238 selected_sources_set.end()) { |
| 239 selected_sources_set.insert(contributing_source.source); |
| 240 contributing_sources_.push_back(contributing_source); |
| 241 } |
| 242 } |
| 243 |
| 244 // Add the contributing source using the SSRC. |
| 245 contributing_sources_.push_back(ssrc_source_); |
| 246 } // End critsect. |
| 247 |
| 248 return contributing_sources_; |
| 249 } |
| 250 |
| 206 bool RtpReceiverImpl::Timestamp(uint32_t* timestamp) const { | 251 bool RtpReceiverImpl::Timestamp(uint32_t* timestamp) const { |
| 207 rtc::CritScope lock(&critical_section_rtp_receiver_); | 252 rtc::CritScope lock(&critical_section_rtp_receiver_); |
| 208 if (!HaveReceivedFrame()) | 253 if (!HaveReceivedFrame()) |
| 209 return false; | 254 return false; |
| 210 *timestamp = last_received_timestamp_; | 255 *timestamp = last_received_timestamp_; |
| 211 return true; | 256 return true; |
| 212 } | 257 } |
| 213 | 258 |
| 214 bool RtpReceiverImpl::LastReceivedTimeMs(int64_t* receive_time_ms) const { | 259 bool RtpReceiverImpl::LastReceivedTimeMs(int64_t* receive_time_ms) const { |
| 215 rtc::CritScope lock(&critical_section_rtp_receiver_); | 260 rtc::CritScope lock(&critical_section_rtp_receiver_); |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 454 // Using CSRC 0 to signal this event, not interop safe, other | 499 // Using CSRC 0 to signal this event, not interop safe, other |
| 455 // implementations might have CSRC 0 as a valid value. | 500 // implementations might have CSRC 0 as a valid value. |
| 456 if (num_csrcs_diff > 0) { | 501 if (num_csrcs_diff > 0) { |
| 457 cb_rtp_feedback_->OnIncomingCSRCChanged(0, true); | 502 cb_rtp_feedback_->OnIncomingCSRCChanged(0, true); |
| 458 } else if (num_csrcs_diff < 0) { | 503 } else if (num_csrcs_diff < 0) { |
| 459 cb_rtp_feedback_->OnIncomingCSRCChanged(0, false); | 504 cb_rtp_feedback_->OnIncomingCSRCChanged(0, false); |
| 460 } | 505 } |
| 461 } | 506 } |
| 462 } | 507 } |
| 463 | 508 |
| 509 void RtpReceiverImpl::UpdateContributingSource() { |
| 510 rtc::CritScope lock(&critical_section_rtp_receiver_); |
| 511 int64_t now = clock_->TimeInMilliseconds(); |
| 512 for (size_t i = 0; i < num_csrcs_; ++i) { |
| 513 contributing_sources_buffer_[current_buffer_index_].timestamp = now; |
| 514 contributing_sources_buffer_[current_buffer_index_].source = |
| 515 current_remote_csrc_[i]; |
| 516 current_buffer_index_ = |
| 517 (current_buffer_index_ + 1) % kContributingSourcesBufferSize; |
| 518 |
| 519 if (current_buffer_size_ < kContributingSourcesBufferSize) { |
| 520 ++current_buffer_size_; |
| 521 } |
| 522 } |
| 523 |
| 524 // If the SSRC is changed and the old SSRC has been kept for more than |
| 525 // |kContributingSourcesTimeoutMs| or this is the first RTP packet, update |
| 526 // both the ssrc and timestamp. |
| 527 // If the SSRC isn't changed, just update the timestamp. |
| 528 if ((now - ssrc_source_.timestamp) > kContributingSourcesTimeoutMs || |
| 529 ssrc_source_.source == 0) { |
| 530 ssrc_source_.timestamp = now; |
| 531 ssrc_source_.source = ssrc_; |
| 532 } else if (ssrc_ == ssrc_source_.source) { |
| 533 ssrc_source_.timestamp = now; |
| 534 } |
| 535 } |
| 536 |
| 464 } // namespace webrtc | 537 } // namespace webrtc |
| OLD | NEW |