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