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 kContributingSourcesTimeout = 10000; // ms | |
hbos
2017/03/30 09:51:54
Prefer ms in the name, kContributingSourcesTimeout
Zhi Huang
2017/03/31 06:44:04
Done.
| |
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() { | |
hbos
2017/03/30 09:51:54
What's the threading model. Should we either lock
Zhi Huang
2017/03/31 06:44:04
This method should only be called on the worker_th
| |
217 contributing_sources_.clear(); | |
Taylor Brandstetter
2017/03/30 22:55:37
If contributing_sources_ is only used in this meth
Zhi Huang
2017/03/31 06:44:04
If it returns the vector by value then I have to c
Taylor Brandstetter
2017/03/31 22:10:50
With C++11, the compiler should optimize away the
| |
218 std::set<uint32_t> selected_sources_set; | |
219 int64_t now = clock_->TimeInMilliseconds(); | |
220 | |
221 for (size_t i = 1; i <= current_buffer_size_; ++i) { | |
222 // Iterate the buffer in reverse order. | |
223 size_t index = | |
224 (current_buffer_index_ + kContributingSourcesBufferSize - i) % | |
225 kContributingSourcesBufferSize; | |
226 RtpContributingSource& contributing_source = | |
227 contributing_sources_buffer_[index]; | |
228 // Stop iterating when the contributing source object is out of date since | |
229 // the buffer is ordered by the timestamp. | |
230 if (now - contributing_source.timestamp() > kContributingSourcesTimeout) { | |
231 break; | |
232 } | |
233 // Return the latest timestamp for a given SSRC and skip the duplicated | |
234 // ones. | |
235 if (selected_sources_set.find(contributing_source.source()) == | |
236 selected_sources_set.end()) { | |
237 selected_sources_set.insert(contributing_source.source()); | |
238 contributing_sources_.push_back(&contributing_source); | |
the sun
2017/03/30 11:31:42
IIUC, UpdateContributingSource() will be called on
Zhi Huang
2017/03/31 06:44:04
I think there are two options to solve this:
1) Wh
| |
239 } | |
240 } | |
241 // Add the contributing source using the SSRC. | |
Taylor Brandstetter
2017/03/30 22:55:37
This doesn't properly handle the corner case of th
Zhi Huang
2017/03/31 06:44:04
According to the spec:
"If the RTP packet contains
Taylor Brandstetter
2017/03/31 22:10:50
That was the topic of this issue on github: https:
| |
242 ssrc_source_.reset(new RtpContributingSource(now, ssrc_)); | |
hbos
2017/03/30 09:51:54
I thought the SSRC was a special case of CSRC, but
Zhi Huang
2017/03/31 06:44:04
I'll just use the plain old structs and return a c
| |
243 contributing_sources_.push_back(ssrc_source_.get()); | |
244 | |
245 return contributing_sources_; | |
hbos
2017/03/30 09:51:54
Since this is returning raw pointers can you docum
| |
246 } | |
247 | |
206 bool RtpReceiverImpl::Timestamp(uint32_t* timestamp) const { | 248 bool RtpReceiverImpl::Timestamp(uint32_t* timestamp) const { |
207 rtc::CritScope lock(&critical_section_rtp_receiver_); | 249 rtc::CritScope lock(&critical_section_rtp_receiver_); |
208 if (!HaveReceivedFrame()) | 250 if (!HaveReceivedFrame()) |
209 return false; | 251 return false; |
210 *timestamp = last_received_timestamp_; | 252 *timestamp = last_received_timestamp_; |
211 return true; | 253 return true; |
212 } | 254 } |
213 | 255 |
214 bool RtpReceiverImpl::LastReceivedTimeMs(int64_t* receive_time_ms) const { | 256 bool RtpReceiverImpl::LastReceivedTimeMs(int64_t* receive_time_ms) const { |
215 rtc::CritScope lock(&critical_section_rtp_receiver_); | 257 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 | 496 // Using CSRC 0 to signal this event, not interop safe, other |
455 // implementations might have CSRC 0 as a valid value. | 497 // implementations might have CSRC 0 as a valid value. |
456 if (num_csrcs_diff > 0) { | 498 if (num_csrcs_diff > 0) { |
457 cb_rtp_feedback_->OnIncomingCSRCChanged(0, true); | 499 cb_rtp_feedback_->OnIncomingCSRCChanged(0, true); |
458 } else if (num_csrcs_diff < 0) { | 500 } else if (num_csrcs_diff < 0) { |
459 cb_rtp_feedback_->OnIncomingCSRCChanged(0, false); | 501 cb_rtp_feedback_->OnIncomingCSRCChanged(0, false); |
460 } | 502 } |
461 } | 503 } |
462 } | 504 } |
463 | 505 |
506 void RtpReceiverImpl::UpdateContributingSource() { | |
hbos
2017/03/30 09:51:54
Just checking: This is thread safe without holding
Zhi Huang
2017/03/31 06:44:04
I added a lock here because the objects need to be
| |
507 int64_t now = clock_->TimeInMilliseconds(); | |
508 for (size_t i = 0; i < num_csrcs_; ++i) { | |
509 RtpContributingSource contributing_source(now, current_remote_csrc_[i]); | |
510 contributing_sources_buffer_[current_buffer_index_] = contributing_source; | |
hbos
2017/03/30 09:51:54
nit: = RtpContributingSource(... or std::move to m
Zhi Huang
2017/03/31 06:44:04
Done.
| |
511 current_buffer_index_ = | |
512 (current_buffer_index_ + 1) % kContributingSourcesBufferSize; | |
513 | |
514 if (current_buffer_size_ < kContributingSourcesBufferSize) { | |
515 ++current_buffer_size_; | |
516 } | |
517 } | |
Taylor Brandstetter
2017/03/30 22:55:37
I think your initial idea (std::list of sources so
Zhi Huang
2017/03/31 06:44:04
I can change it once we have an agreement on this.
the sun
2017/03/31 07:03:49
Yeah, I don't particularly like that property eith
the sun
2017/04/01 12:23:02
Oh, I just realized the remove/push_back can be ac
| |
518 } | |
519 | |
464 } // namespace webrtc | 520 } // namespace webrtc |
OLD | NEW |