1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
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
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.h"
12
13 #include <assert.h>
14 #include <math.h>
15 #include <stdlib.h>
16 #include <string.h>
17
18 #include "webrtc/base/logging.h"
19 #include "webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h"
20 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
21 #include "webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.h"
22
23 namespace webrtc {
24
25 using RtpUtility::Payload;
26 using RtpUtility::StringCompare;
27
CreateVideoReceiver(Clock * clock,RtpData * incoming_payload_callback,RtpFeedback * incoming_messages_callback,RTPPayloadRegistry * rtp_payload_registry)28 RtpReceiver* RtpReceiver::CreateVideoReceiver(
29 Clock* clock,
30 RtpData* incoming_payload_callback,
31 RtpFeedback* incoming_messages_callback,
32 RTPPayloadRegistry* rtp_payload_registry) {
33 if (!incoming_payload_callback)
34 incoming_payload_callback = NullObjectRtpData();
35 if (!incoming_messages_callback)
36 incoming_messages_callback = NullObjectRtpFeedback();
37 return new RtpReceiverImpl(
38 clock, NullObjectRtpAudioFeedback(), incoming_messages_callback,
39 rtp_payload_registry,
40 RTPReceiverStrategy::CreateVideoStrategy(incoming_payload_callback));
41 }
42
CreateAudioReceiver(Clock * clock,RtpAudioFeedback * incoming_audio_feedback,RtpData * incoming_payload_callback,RtpFeedback * incoming_messages_callback,RTPPayloadRegistry * rtp_payload_registry)43 RtpReceiver* RtpReceiver::CreateAudioReceiver(
44 Clock* clock,
45 RtpAudioFeedback* incoming_audio_feedback,
46 RtpData* incoming_payload_callback,
47 RtpFeedback* incoming_messages_callback,
48 RTPPayloadRegistry* rtp_payload_registry) {
49 if (!incoming_audio_feedback)
50 incoming_audio_feedback = NullObjectRtpAudioFeedback();
51 if (!incoming_payload_callback)
52 incoming_payload_callback = NullObjectRtpData();
53 if (!incoming_messages_callback)
54 incoming_messages_callback = NullObjectRtpFeedback();
55 return new RtpReceiverImpl(
56 clock, incoming_audio_feedback, incoming_messages_callback,
57 rtp_payload_registry,
58 RTPReceiverStrategy::CreateAudioStrategy(incoming_payload_callback,
59 incoming_audio_feedback));
60 }
61
RtpReceiverImpl(Clock * clock,RtpAudioFeedback * incoming_audio_messages_callback,RtpFeedback * incoming_messages_callback,RTPPayloadRegistry * rtp_payload_registry,RTPReceiverStrategy * rtp_media_receiver)62 RtpReceiverImpl::RtpReceiverImpl(
63 Clock* clock,
64 RtpAudioFeedback* incoming_audio_messages_callback,
65 RtpFeedback* incoming_messages_callback,
66 RTPPayloadRegistry* rtp_payload_registry,
67 RTPReceiverStrategy* rtp_media_receiver)
68 : clock_(clock),
69 rtp_payload_registry_(rtp_payload_registry),
70 rtp_media_receiver_(rtp_media_receiver),
71 cb_rtp_feedback_(incoming_messages_callback),
72 critical_section_rtp_receiver_(
73 CriticalSectionWrapper::CreateCriticalSection()),
74 last_receive_time_(0),
75 last_received_payload_length_(0),
76 ssrc_(0),
77 num_csrcs_(0),
78 current_remote_csrc_(),
79 last_received_timestamp_(0),
80 last_received_frame_time_ms_(-1),
81 last_received_sequence_number_(0),
82 nack_method_(kNackOff) {
83 assert(incoming_audio_messages_callback);
84 assert(incoming_messages_callback);
85
86 memset(current_remote_csrc_, 0, sizeof(current_remote_csrc_));
87 }
88
~RtpReceiverImpl()89 RtpReceiverImpl::~RtpReceiverImpl() {
90 for (int i = 0; i < num_csrcs_; ++i) {
91 cb_rtp_feedback_->OnIncomingCSRCChanged(current_remote_csrc_[i], false);
92 }
93 }
94
RegisterReceivePayload(const char payload_name[RTP_PAYLOAD_NAME_SIZE],const int8_t payload_type,const uint32_t frequency,const size_t channels,const uint32_t rate)95 int32_t RtpReceiverImpl::RegisterReceivePayload(
96 const char payload_name[RTP_PAYLOAD_NAME_SIZE],
97 const int8_t payload_type,
98 const uint32_t frequency,
99 const size_t channels,
100 const uint32_t rate) {
101 CriticalSectionScoped lock(critical_section_rtp_receiver_.get());
102
103 // TODO(phoglund): Try to streamline handling of the RED codec and some other
104 // cases which makes it necessary to keep track of whether we created a
105 // payload or not.
106 bool created_new_payload = false;
107 int32_t result = rtp_payload_registry_->RegisterReceivePayload(
108 payload_name, payload_type, frequency, channels, rate,
109 &created_new_payload);
110 if (created_new_payload) {
111 if (rtp_media_receiver_->OnNewPayloadTypeCreated(payload_name, payload_type,
112 frequency) != 0) {
113 LOG(LS_ERROR) << "Failed to register payload: " << payload_name << "/"
114 << static_cast<int>(payload_type);
115 return -1;
116 }
117 }
118 return result;
119 }
120
DeRegisterReceivePayload(const int8_t payload_type)121 int32_t RtpReceiverImpl::DeRegisterReceivePayload(
122 const int8_t payload_type) {
123 CriticalSectionScoped lock(critical_section_rtp_receiver_.get());
124 return rtp_payload_registry_->DeRegisterReceivePayload(payload_type);
125 }
126
NACK() const127 NACKMethod RtpReceiverImpl::NACK() const {
128 CriticalSectionScoped lock(critical_section_rtp_receiver_.get());
129 return nack_method_;
130 }
131
132 // Turn negative acknowledgment requests on/off.
SetNACKStatus(const NACKMethod method)133 void RtpReceiverImpl::SetNACKStatus(const NACKMethod method) {
134 CriticalSectionScoped lock(critical_section_rtp_receiver_.get());
135 nack_method_ = method;
136 }
137
SSRC() const138 uint32_t RtpReceiverImpl::SSRC() const {
139 CriticalSectionScoped lock(critical_section_rtp_receiver_.get());
140 return ssrc_;
141 }
142
143 // Get remote CSRC.
CSRCs(uint32_t array_of_csrcs[kRtpCsrcSize]) const144 int32_t RtpReceiverImpl::CSRCs(uint32_t array_of_csrcs[kRtpCsrcSize]) const {
145 CriticalSectionScoped lock(critical_section_rtp_receiver_.get());
146
147 assert(num_csrcs_ <= kRtpCsrcSize);
148
149 if (num_csrcs_ > 0) {
150 memcpy(array_of_csrcs, current_remote_csrc_, sizeof(uint32_t)*num_csrcs_);
151 }
152 return num_csrcs_;
153 }
154
Energy(uint8_t array_of_energy[kRtpCsrcSize]) const155 int32_t RtpReceiverImpl::Energy(
156 uint8_t array_of_energy[kRtpCsrcSize]) const {
157 return rtp_media_receiver_->Energy(array_of_energy);
158 }
159
IncomingRtpPacket(const RTPHeader & rtp_header,const uint8_t * payload,size_t payload_length,PayloadUnion payload_specific,bool in_order)160 bool RtpReceiverImpl::IncomingRtpPacket(
161 const RTPHeader& rtp_header,
162 const uint8_t* payload,
163 size_t payload_length,
164 PayloadUnion payload_specific,
165 bool in_order) {
166 // Trigger our callbacks.
167 CheckSSRCChanged(rtp_header);
168
169 int8_t first_payload_byte = payload_length > 0 ? payload[0] : 0;
170 bool is_red = false;
171
172 if (CheckPayloadChanged(rtp_header, first_payload_byte, &is_red,
173 &payload_specific) == -1) {
174 if (payload_length == 0) {
175 // OK, keep-alive packet.
176 return true;
177 }
178 LOG(LS_WARNING) << "Receiving invalid payload type.";
179 return false;
180 }
181
182 WebRtcRTPHeader webrtc_rtp_header;
183 memset(&webrtc_rtp_header, 0, sizeof(webrtc_rtp_header));
184 webrtc_rtp_header.header = rtp_header;
185 CheckCSRC(webrtc_rtp_header);
186
187 size_t payload_data_length = payload_length - rtp_header.paddingLength;
188
189 bool is_first_packet_in_frame = false;
190 {
191 CriticalSectionScoped lock(critical_section_rtp_receiver_.get());
192 if (HaveReceivedFrame()) {
193 is_first_packet_in_frame =
194 last_received_sequence_number_ + 1 == rtp_header.sequenceNumber &&
195 last_received_timestamp_ != rtp_header.timestamp;
196 } else {
197 is_first_packet_in_frame = true;
198 }
199 }
200
201 int32_t ret_val = rtp_media_receiver_->ParseRtpPacket(
202 &webrtc_rtp_header, payload_specific, is_red, payload, payload_length,
203 clock_->TimeInMilliseconds(), is_first_packet_in_frame);
204
205 if (ret_val < 0) {
206 return false;
207 }
208
209 {
210 CriticalSectionScoped lock(critical_section_rtp_receiver_.get());
211
212 last_receive_time_ = clock_->TimeInMilliseconds();
213 last_received_payload_length_ = payload_data_length;
214
215 if (in_order) {
216 if (last_received_timestamp_ != rtp_header.timestamp) {
217 last_received_timestamp_ = rtp_header.timestamp;
218 last_received_frame_time_ms_ = clock_->TimeInMilliseconds();
219 }
220 last_received_sequence_number_ = rtp_header.sequenceNumber;
221 }
222 }
223 return true;
224 }
225
GetTelephoneEventHandler()226 TelephoneEventHandler* RtpReceiverImpl::GetTelephoneEventHandler() {
227 return rtp_media_receiver_->GetTelephoneEventHandler();
228 }
229
Timestamp(uint32_t * timestamp) const230 bool RtpReceiverImpl::Timestamp(uint32_t* timestamp) const {
231 CriticalSectionScoped lock(critical_section_rtp_receiver_.get());
232 if (!HaveReceivedFrame())
233 return false;
234 *timestamp = last_received_timestamp_;
235 return true;
236 }
237
LastReceivedTimeMs(int64_t * receive_time_ms) const238 bool RtpReceiverImpl::LastReceivedTimeMs(int64_t* receive_time_ms) const {
239 CriticalSectionScoped lock(critical_section_rtp_receiver_.get());
240 if (!HaveReceivedFrame())
241 return false;
242 *receive_time_ms = last_received_frame_time_ms_;
243 return true;
244 }
245
HaveReceivedFrame() const246 bool RtpReceiverImpl::HaveReceivedFrame() const {
247 return last_received_frame_time_ms_ >= 0;
248 }
249
250 // Implementation note: must not hold critsect when called.
CheckSSRCChanged(const RTPHeader & rtp_header)251 void RtpReceiverImpl::CheckSSRCChanged(const RTPHeader& rtp_header) {
252 bool new_ssrc = false;
253 bool re_initialize_decoder = false;
254 char payload_name[RTP_PAYLOAD_NAME_SIZE];
255 size_t channels = 1;
256 uint32_t rate = 0;
257
258 {
259 CriticalSectionScoped lock(critical_section_rtp_receiver_.get());
260
261 int8_t last_received_payload_type =
262 rtp_payload_registry_->last_received_payload_type();
263 if (ssrc_ != rtp_header.ssrc ||
264 (last_received_payload_type == -1 && ssrc_ == 0)) {
265 // We need the payload_type_ to make the call if the remote SSRC is 0.
266 new_ssrc = true;
267
268 last_received_timestamp_ = 0;
269 last_received_sequence_number_ = 0;
270 last_received_frame_time_ms_ = -1;
271
272 // Do we have a SSRC? Then the stream is restarted.
273 if (ssrc_ != 0) {
274 // Do we have the same codec? Then re-initialize coder.
275 if (rtp_header.payloadType == last_received_payload_type) {
276 re_initialize_decoder = true;
277
278 const Payload* payload = rtp_payload_registry_->PayloadTypeToPayload(
279 rtp_header.payloadType);
280 if (!payload) {
281 return;
282 }
283 payload_name[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
284 strncpy(payload_name, payload->name, RTP_PAYLOAD_NAME_SIZE - 1);
285 if (payload->audio) {
286 channels = payload->typeSpecific.Audio.channels;
287 rate = payload->typeSpecific.Audio.rate;
288 }
289 }
290 }
291 ssrc_ = rtp_header.ssrc;
292 }
293 }
294
295 if (new_ssrc) {
296 // We need to get this to our RTCP sender and receiver.
297 // We need to do this outside critical section.
298 cb_rtp_feedback_->OnIncomingSSRCChanged(rtp_header.ssrc);
299 }
300
301 if (re_initialize_decoder) {
302 if (-1 ==
303 cb_rtp_feedback_->OnInitializeDecoder(
304 rtp_header.payloadType, payload_name,
305 rtp_header.payload_type_frequency, channels, rate)) {
306 // New stream, same codec.
307 LOG(LS_ERROR) << "Failed to create decoder for payload type: "
308 << static_cast<int>(rtp_header.payloadType);
309 }
310 }
311 }
312
313 // Implementation note: must not hold critsect when called.
314 // TODO(phoglund): Move as much as possible of this code path into the media
315 // specific receivers. Basically this method goes through a lot of trouble to
316 // compute something which is only used by the media specific parts later. If
317 // this code path moves we can get rid of some of the rtp_receiver ->
318 // media_specific interface (such as CheckPayloadChange, possibly get/set
319 // last known payload).
CheckPayloadChanged(const RTPHeader & rtp_header,const int8_t first_payload_byte,bool * is_red,PayloadUnion * specific_payload)320 int32_t RtpReceiverImpl::CheckPayloadChanged(const RTPHeader& rtp_header,
321 const int8_t first_payload_byte,
322 bool* is_red,
323 PayloadUnion* specific_payload) {
324 bool re_initialize_decoder = false;
325
326 char payload_name[RTP_PAYLOAD_NAME_SIZE];
327 int8_t payload_type = rtp_header.payloadType;
328
329 {
330 CriticalSectionScoped lock(critical_section_rtp_receiver_.get());
331
332 int8_t last_received_payload_type =
333 rtp_payload_registry_->last_received_payload_type();
334 // TODO(holmer): Remove this code when RED parsing has been broken out from
335 // RtpReceiverAudio.
336 if (payload_type != last_received_payload_type) {
337 if (rtp_payload_registry_->red_payload_type() == payload_type) {
338 // Get the real codec payload type.
339 payload_type = first_payload_byte & 0x7f;
340 *is_red = true;
341
342 if (rtp_payload_registry_->red_payload_type() == payload_type) {
343 // Invalid payload type, traced by caller. If we proceeded here,
344 // this would be set as |_last_received_payload_type|, and we would no
345 // longer catch corrupt packets at this level.
346 return -1;
347 }
348
349 // When we receive RED we need to check the real payload type.
350 if (payload_type == last_received_payload_type) {
351 rtp_media_receiver_->GetLastMediaSpecificPayload(specific_payload);
352 return 0;
353 }
354 }
355 bool should_discard_changes = false;
356
357 rtp_media_receiver_->CheckPayloadChanged(
358 payload_type, specific_payload,
359 &should_discard_changes);
360
361 if (should_discard_changes) {
362 *is_red = false;
363 return 0;
364 }
365
366 const Payload* payload =
367 rtp_payload_registry_->PayloadTypeToPayload(payload_type);
368 if (!payload) {
369 // Not a registered payload type.
370 return -1;
371 }
372 payload_name[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
373 strncpy(payload_name, payload->name, RTP_PAYLOAD_NAME_SIZE - 1);
374
375 rtp_payload_registry_->set_last_received_payload_type(payload_type);
376
377 re_initialize_decoder = true;
378
379 rtp_media_receiver_->SetLastMediaSpecificPayload(payload->typeSpecific);
380 rtp_media_receiver_->GetLastMediaSpecificPayload(specific_payload);
381
382 if (!payload->audio) {
383 bool media_type_unchanged =
384 rtp_payload_registry_->ReportMediaPayloadType(payload_type);
385 if (media_type_unchanged) {
386 // Only reset the decoder if the media codec type has changed.
387 re_initialize_decoder = false;
388 }
389 }
390 } else {
391 rtp_media_receiver_->GetLastMediaSpecificPayload(specific_payload);
392 *is_red = false;
393 }
394 } // End critsect.
395
396 if (re_initialize_decoder) {
397 if (-1 ==
398 rtp_media_receiver_->InvokeOnInitializeDecoder(
399 cb_rtp_feedback_, payload_type, payload_name, *specific_payload)) {
400 return -1; // Wrong payload type.
401 }
402 }
403 return 0;
404 }
405
406 // Implementation note: must not hold critsect when called.
CheckCSRC(const WebRtcRTPHeader & rtp_header)407 void RtpReceiverImpl::CheckCSRC(const WebRtcRTPHeader& rtp_header) {
408 int32_t num_csrcs_diff = 0;
409 uint32_t old_remote_csrc[kRtpCsrcSize];
410 uint8_t old_num_csrcs = 0;
411
412 {
413 CriticalSectionScoped lock(critical_section_rtp_receiver_.get());
414
415 if (!rtp_media_receiver_->ShouldReportCsrcChanges(
416 rtp_header.header.payloadType)) {
417 return;
418 }
419 old_num_csrcs = num_csrcs_;
420 if (old_num_csrcs > 0) {
421 // Make a copy of old.
422 memcpy(old_remote_csrc, current_remote_csrc_,
423 num_csrcs_ * sizeof(uint32_t));
424 }
425 const uint8_t num_csrcs = rtp_header.header.numCSRCs;
426 if ((num_csrcs > 0) && (num_csrcs <= kRtpCsrcSize)) {
427 // Copy new.
428 memcpy(current_remote_csrc_,
429 rtp_header.header.arrOfCSRCs,
430 num_csrcs * sizeof(uint32_t));
431 }
432 if (num_csrcs > 0 || old_num_csrcs > 0) {
433 num_csrcs_diff = num_csrcs - old_num_csrcs;
434 num_csrcs_ = num_csrcs; // Update stored CSRCs.
435 } else {
436 // No change.
437 return;
438 }
439 } // End critsect.
440
441 bool have_called_callback = false;
442 // Search for new CSRC in old array.
443 for (uint8_t i = 0; i < rtp_header.header.numCSRCs; ++i) {
444 const uint32_t csrc = rtp_header.header.arrOfCSRCs[i];
445
446 bool found_match = false;
447 for (uint8_t j = 0; j < old_num_csrcs; ++j) {
448 if (csrc == old_remote_csrc[j]) { // old list
449 found_match = true;
450 break;
451 }
452 }
453 if (!found_match && csrc) {
454 // Didn't find it, report it as new.
455 have_called_callback = true;
456 cb_rtp_feedback_->OnIncomingCSRCChanged(csrc, true);
457 }
458 }
459 // Search for old CSRC in new array.
460 for (uint8_t i = 0; i < old_num_csrcs; ++i) {
461 const uint32_t csrc = old_remote_csrc[i];
462
463 bool found_match = false;
464 for (uint8_t j = 0; j < rtp_header.header.numCSRCs; ++j) {
465 if (csrc == rtp_header.header.arrOfCSRCs[j]) {
466 found_match = true;
467 break;
468 }
469 }
470 if (!found_match && csrc) {
471 // Did not find it, report as removed.
472 have_called_callback = true;
473 cb_rtp_feedback_->OnIncomingCSRCChanged(csrc, false);
474 }
475 }
476 if (!have_called_callback) {
477 // If the CSRC list contain non-unique entries we will end up here.
478 // Using CSRC 0 to signal this event, not interop safe, other
479 // implementations might have CSRC 0 as a valid value.
480 if (num_csrcs_diff > 0) {
481 cb_rtp_feedback_->OnIncomingCSRCChanged(0, true);
482 } else if (num_csrcs_diff < 0) {
483 cb_rtp_feedback_->OnIncomingCSRCChanged(0, false);
484 }
485 }
486 }
487
488 } // namespace webrtc
489