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 sources in the last 10 seconds. | |
30 static const int64_t kGetSourcesTimeoutMs = 10000; | |
danilchap
2017/04/05 16:24:21
constants outside class doesn't have to be marked
Zhi Huang
2017/04/06 03:09:49
Done.
the sun
2017/04/06 06:55:37
They should still be made private to the translati
| |
31 | |
32 // The maximum size of the sources lists. | |
the sun
2017/04/05 14:58:30
nit: "The maximum combined size"...
Zhi Huang
2017/04/06 03:09:50
Done.
| |
33 static const int kMaxSourceListsSize = 100; | |
34 | |
26 using RtpUtility::Payload; | 35 using RtpUtility::Payload; |
27 | 36 |
28 RtpReceiver* RtpReceiver::CreateVideoReceiver( | 37 RtpReceiver* RtpReceiver::CreateVideoReceiver( |
29 Clock* clock, | 38 Clock* clock, |
30 RtpData* incoming_payload_callback, | 39 RtpData* incoming_payload_callback, |
31 RtpFeedback* incoming_messages_callback, | 40 RtpFeedback* incoming_messages_callback, |
32 RTPPayloadRegistry* rtp_payload_registry) { | 41 RTPPayloadRegistry* rtp_payload_registry) { |
33 if (!incoming_payload_callback) | 42 if (!incoming_payload_callback) |
34 incoming_payload_callback = NullObjectRtpData(); | 43 incoming_payload_callback = NullObjectRtpData(); |
35 if (!incoming_messages_callback) | 44 if (!incoming_messages_callback) |
(...skipping 10 matching lines...) Expand all Loading... | |
46 RTPPayloadRegistry* rtp_payload_registry) { | 55 RTPPayloadRegistry* rtp_payload_registry) { |
47 if (!incoming_payload_callback) | 56 if (!incoming_payload_callback) |
48 incoming_payload_callback = NullObjectRtpData(); | 57 incoming_payload_callback = NullObjectRtpData(); |
49 if (!incoming_messages_callback) | 58 if (!incoming_messages_callback) |
50 incoming_messages_callback = NullObjectRtpFeedback(); | 59 incoming_messages_callback = NullObjectRtpFeedback(); |
51 return new RtpReceiverImpl( | 60 return new RtpReceiverImpl( |
52 clock, incoming_messages_callback, rtp_payload_registry, | 61 clock, incoming_messages_callback, rtp_payload_registry, |
53 RTPReceiverStrategy::CreateAudioStrategy(incoming_payload_callback)); | 62 RTPReceiverStrategy::CreateAudioStrategy(incoming_payload_callback)); |
54 } | 63 } |
55 | 64 |
56 RtpReceiverImpl::RtpReceiverImpl( | 65 RtpReceiverImpl::RtpReceiverImpl(Clock* clock, |
57 Clock* clock, | 66 RtpFeedback* incoming_messages_callback, |
58 RtpFeedback* incoming_messages_callback, | 67 RTPPayloadRegistry* rtp_payload_registry, |
59 RTPPayloadRegistry* rtp_payload_registry, | 68 RTPReceiverStrategy* rtp_media_receiver) |
60 RTPReceiverStrategy* rtp_media_receiver) | |
61 : clock_(clock), | 69 : clock_(clock), |
62 rtp_payload_registry_(rtp_payload_registry), | 70 rtp_payload_registry_(rtp_payload_registry), |
63 rtp_media_receiver_(rtp_media_receiver), | 71 rtp_media_receiver_(rtp_media_receiver), |
64 cb_rtp_feedback_(incoming_messages_callback), | 72 cb_rtp_feedback_(incoming_messages_callback), |
65 last_receive_time_(0), | 73 last_receive_time_(0), |
66 last_received_payload_length_(0), | 74 last_received_payload_length_(0), |
67 ssrc_(0), | 75 ssrc_(0), |
68 num_csrcs_(0), | 76 num_csrcs_(0), |
69 current_remote_csrc_(), | 77 current_remote_csrc_(), |
70 last_received_timestamp_(0), | 78 last_received_timestamp_(0), |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
153 } | 161 } |
154 LOG(LS_WARNING) << "Receiving invalid payload type."; | 162 LOG(LS_WARNING) << "Receiving invalid payload type."; |
155 return false; | 163 return false; |
156 } | 164 } |
157 | 165 |
158 WebRtcRTPHeader webrtc_rtp_header; | 166 WebRtcRTPHeader webrtc_rtp_header; |
159 memset(&webrtc_rtp_header, 0, sizeof(webrtc_rtp_header)); | 167 memset(&webrtc_rtp_header, 0, sizeof(webrtc_rtp_header)); |
160 webrtc_rtp_header.header = rtp_header; | 168 webrtc_rtp_header.header = rtp_header; |
161 CheckCSRC(webrtc_rtp_header); | 169 CheckCSRC(webrtc_rtp_header); |
162 | 170 |
171 UpdateSources(); | |
172 | |
163 size_t payload_data_length = payload_length - rtp_header.paddingLength; | 173 size_t payload_data_length = payload_length - rtp_header.paddingLength; |
164 | 174 |
165 bool is_first_packet_in_frame = false; | 175 bool is_first_packet_in_frame = false; |
166 { | 176 { |
167 rtc::CritScope lock(&critical_section_rtp_receiver_); | 177 rtc::CritScope lock(&critical_section_rtp_receiver_); |
168 if (HaveReceivedFrame()) { | 178 if (HaveReceivedFrame()) { |
169 is_first_packet_in_frame = | 179 is_first_packet_in_frame = |
170 last_received_sequence_number_ + 1 == rtp_header.sequenceNumber && | 180 last_received_sequence_number_ + 1 == rtp_header.sequenceNumber && |
171 last_received_timestamp_ != rtp_header.timestamp; | 181 last_received_timestamp_ != rtp_header.timestamp; |
172 } else { | 182 } else { |
(...skipping 23 matching lines...) Expand all Loading... | |
196 last_received_sequence_number_ = rtp_header.sequenceNumber; | 206 last_received_sequence_number_ = rtp_header.sequenceNumber; |
197 } | 207 } |
198 } | 208 } |
199 return true; | 209 return true; |
200 } | 210 } |
201 | 211 |
202 TelephoneEventHandler* RtpReceiverImpl::GetTelephoneEventHandler() { | 212 TelephoneEventHandler* RtpReceiverImpl::GetTelephoneEventHandler() { |
203 return rtp_media_receiver_->GetTelephoneEventHandler(); | 213 return rtp_media_receiver_->GetTelephoneEventHandler(); |
204 } | 214 } |
205 | 215 |
216 const std::vector<RtpSource> RtpReceiverImpl::GetSources() { | |
217 int64_t now = clock_->TimeInMilliseconds(); | |
218 std::vector<RtpSource> sources; | |
219 | |
220 { | |
221 rtc::CritScope lock(&critical_section_rtp_receiver_); | |
222 | |
the sun
2017/04/05 14:58:30
Since we assume that the lists are sorted in the b
Zhi Huang
2017/04/06 03:09:49
Done.
| |
223 std::set<uint32_t> selected_ssrcs; | |
224 for (auto rit = ssrc_sources_.rbegin(); rit != ssrc_sources_.rend(); | |
225 ++rit) { | |
226 if (now - rit->timestamp() > kGetSourcesTimeoutMs) { | |
the sun
2017/04/05 14:58:30
nit: () around the subtraction, here and below
Zhi Huang
2017/04/06 03:09:50
Done.
| |
227 break; | |
228 } | |
229 if (selected_ssrcs.find(rit->source_id()) == selected_ssrcs.end()) { | |
danilchap
2017/04/05 16:24:21
to avoid double lookup you can use return value of
Zhi Huang
2017/04/06 03:09:50
Done.
| |
230 selected_ssrcs.insert(rit->source_id()); | |
231 sources.push_back(*rit); | |
232 } | |
233 } | |
234 | |
235 for (auto rit = csrc_sources_.rbegin(); rit != csrc_sources_.rend(); | |
236 ++rit) { | |
237 if (now - rit->timestamp() > kGetSourcesTimeoutMs) { | |
238 break; | |
239 } | |
240 sources.push_back(*rit); | |
241 } | |
242 } // End critsect. | |
243 | |
244 return sources; | |
245 } | |
246 | |
206 bool RtpReceiverImpl::Timestamp(uint32_t* timestamp) const { | 247 bool RtpReceiverImpl::Timestamp(uint32_t* timestamp) const { |
207 rtc::CritScope lock(&critical_section_rtp_receiver_); | 248 rtc::CritScope lock(&critical_section_rtp_receiver_); |
208 if (!HaveReceivedFrame()) | 249 if (!HaveReceivedFrame()) |
209 return false; | 250 return false; |
210 *timestamp = last_received_timestamp_; | 251 *timestamp = last_received_timestamp_; |
211 return true; | 252 return true; |
212 } | 253 } |
213 | 254 |
214 bool RtpReceiverImpl::LastReceivedTimeMs(int64_t* receive_time_ms) const { | 255 bool RtpReceiverImpl::LastReceivedTimeMs(int64_t* receive_time_ms) const { |
215 rtc::CritScope lock(&critical_section_rtp_receiver_); | 256 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 | 495 // Using CSRC 0 to signal this event, not interop safe, other |
455 // implementations might have CSRC 0 as a valid value. | 496 // implementations might have CSRC 0 as a valid value. |
456 if (num_csrcs_diff > 0) { | 497 if (num_csrcs_diff > 0) { |
457 cb_rtp_feedback_->OnIncomingCSRCChanged(0, true); | 498 cb_rtp_feedback_->OnIncomingCSRCChanged(0, true); |
458 } else if (num_csrcs_diff < 0) { | 499 } else if (num_csrcs_diff < 0) { |
459 cb_rtp_feedback_->OnIncomingCSRCChanged(0, false); | 500 cb_rtp_feedback_->OnIncomingCSRCChanged(0, false); |
460 } | 501 } |
461 } | 502 } |
462 } | 503 } |
463 | 504 |
505 void RtpReceiverImpl::UpdateSources() { | |
506 rtc::CritScope lock(&critical_section_rtp_receiver_); | |
507 int64_t now = clock_->TimeInMilliseconds(); | |
508 | |
509 for (size_t i = 0; i < num_csrcs_; ++i) { | |
510 auto map_it = iterator_by_csrc_.find(current_remote_csrc_[i]); | |
511 if (map_it == iterator_by_csrc_.end()) { | |
512 // If it is a new CSRC, append a new object to the end of the list. | |
513 csrc_sources_.emplace_back(now, current_remote_csrc_[i], | |
514 RtpSourceType::RTP_CSRC_SOURCE); | |
515 } else { | |
516 // If it is an existing CSRC, move the object to the end of the list. | |
517 map_it->second->update_timestamp(now); | |
518 csrc_sources_.splice(csrc_sources_.end(), csrc_sources_, map_it->second); | |
519 } | |
520 // Update the unordered_map. | |
521 iterator_by_csrc_[current_remote_csrc_[i]] = std::prev(csrc_sources_.end()); | |
522 | |
523 // Remove the out of date objects if the lists are too large. | |
hbos
2017/04/05 11:15:41
nit: I think this bit should be moved to the end o
the sun
2017/04/05 14:58:29
Good catch!
Zhi Huang
2017/04/06 03:09:49
Done.
| |
524 if ((csrc_sources_.size() + ssrc_sources_.size()) > kMaxSourceListsSize) { | |
525 UpdateSourceLists(now); | |
526 } | |
527 } | |
528 | |
529 // If this is the first packet or the SSRC is changed, insert a new | |
530 // contributing source that uses the SSRC. | |
531 if (ssrc_sources_.size() == 0 || | |
532 std::prev(ssrc_sources_.end())->source_id() != ssrc_) { | |
533 ssrc_sources_.emplace_back(now, ssrc_, RtpSourceType::RTP_SSRC_SOURCE); | |
534 } else { | |
535 std::prev(ssrc_sources_.end())->update_timestamp(now); | |
536 } | |
537 } | |
538 | |
539 // Update the lists and remove the out of date objects. | |
the sun
2017/04/05 14:58:29
With a different function name you wouldn't need t
Zhi Huang
2017/04/06 03:09:50
I'll remove the length limitation and just call th
the sun
2017/04/06 06:55:38
Much better than my suggestion!
| |
540 void RtpReceiverImpl::UpdateSourceLists(int64_t now) { | |
hbos
2017/04/05 11:15:41
We only throw away outdated objects. Max object co
the sun
2017/04/05 14:58:29
+1
Zhi Huang
2017/04/06 03:09:50
I added this because I thought the idea is to make
| |
541 for (auto it = csrc_sources_.begin(); it != csrc_sources_.end();) { | |
542 if (now - it->timestamp() <= kGetSourcesTimeoutMs) { | |
543 break; | |
544 } | |
545 iterator_by_csrc_.erase(it->source_id()); | |
546 it = csrc_sources_.erase(it); | |
Taylor Brandstetter
2017/04/05 04:27:55
extreme nit: I think this could just do "++it" her
the sun
2017/04/05 14:58:29
Possibly, but likely not since it's a std::list. W
Zhi Huang
2017/04/06 03:09:50
Done.
| |
547 } | |
548 | |
549 for (auto it = ssrc_sources_.begin(); it != ssrc_sources_.end(); ++it) { | |
550 if (now - it->timestamp() <= kGetSourcesTimeoutMs) { | |
551 ssrc_sources_.erase(ssrc_sources_.begin(), it); | |
552 break; | |
553 } | |
hbos
2017/04/05 11:15:41
Because of the break this will at most remove one
the sun
2017/04/05 14:58:30
The idea is to remove all old elements in one go.
Zhi Huang
2017/04/06 03:09:49
I don't think it will only remove one ssrc.
The i
Zhi Huang
2017/04/06 03:09:50
I've added a test for this.
I agree with Taylor (
the sun
2017/04/06 06:55:37
True, both works.
the sun
2017/04/06 06:55:38
Yes, it's a good idea though to mark such function
| |
554 } | |
the sun
2017/04/05 14:58:29
The erase should go here, after searching for the
Zhi Huang
2017/04/06 03:09:50
Alright. This looks more clear.
| |
555 } | |
556 | |
464 } // namespace webrtc | 557 } // namespace webrtc |
OLD | NEW |