1 /* 2 * Copyright (c) 2013 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/interface/rtp_payload_registry.h" 12 13 #include "webrtc/system_wrappers/interface/logging.h" 14 15 namespace webrtc { 16 17 RTPPayloadRegistry::RTPPayloadRegistry( 18 RTPPayloadStrategy* rtp_payload_strategy) 19 : crit_sect_(CriticalSectionWrapper::CreateCriticalSection()), 20 rtp_payload_strategy_(rtp_payload_strategy), 21 red_payload_type_(-1), 22 ulpfec_payload_type_(-1), 23 incoming_payload_type_(-1), 24 last_received_payload_type_(-1), 25 last_received_media_payload_type_(-1), 26 rtx_(false), 27 payload_type_rtx_(-1), 28 ssrc_rtx_(0) {} 29 30 RTPPayloadRegistry::~RTPPayloadRegistry() { 31 while (!payload_type_map_.empty()) { 32 ModuleRTPUtility::PayloadTypeMap::iterator it = payload_type_map_.begin(); 33 delete it->second; 34 payload_type_map_.erase(it); 35 } 36 } 37 38 int32_t RTPPayloadRegistry::RegisterReceivePayload( 39 const char payload_name[RTP_PAYLOAD_NAME_SIZE], 40 const int8_t payload_type, 41 const uint32_t frequency, 42 const uint8_t channels, 43 const uint32_t rate, 44 bool* created_new_payload) { 45 assert(payload_type >= 0); 46 assert(payload_name); 47 *created_new_payload = false; 48 49 // Sanity check. 50 switch (payload_type) { 51 // Reserved payload types to avoid RTCP conflicts when marker bit is set. 52 case 64: // 192 Full INTRA-frame request. 53 case 72: // 200 Sender report. 54 case 73: // 201 Receiver report. 55 case 74: // 202 Source description. 56 case 75: // 203 Goodbye. 57 case 76: // 204 Application-defined. 58 case 77: // 205 Transport layer FB message. 59 case 78: // 206 Payload-specific FB message. 60 case 79: // 207 Extended report. 61 LOG(LS_ERROR) << "Can't register invalid receiver payload type: " 62 << payload_type; 63 return -1; 64 default: 65 break; 66 } 67 68 size_t payload_name_length = strlen(payload_name); 69 70 CriticalSectionScoped cs(crit_sect_.get()); 71 72 ModuleRTPUtility::PayloadTypeMap::iterator it = 73 payload_type_map_.find(payload_type); 74 75 if (it != payload_type_map_.end()) { 76 // We already use this payload type. 77 ModuleRTPUtility::Payload* payload = it->second; 78 79 assert(payload); 80 81 size_t name_length = strlen(payload->name); 82 83 // Check if it's the same as we already have. 84 // If same, ignore sending an error. 85 if (payload_name_length == name_length && 86 ModuleRTPUtility::StringCompare( 87 payload->name, payload_name, payload_name_length)) { 88 if (rtp_payload_strategy_->PayloadIsCompatible(*payload, frequency, 89 channels, rate)) { 90 rtp_payload_strategy_->UpdatePayloadRate(payload, rate); 91 return 0; 92 } 93 } 94 LOG(LS_ERROR) << "Payload type already registered: " << payload_type; 95 return -1; 96 } 97 98 if (rtp_payload_strategy_->CodecsMustBeUnique()) { 99 DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType( 100 payload_name, payload_name_length, frequency, channels, rate); 101 } 102 103 ModuleRTPUtility::Payload* payload = NULL; 104 105 // Save the RED payload type. Used in both audio and video. 106 if (ModuleRTPUtility::StringCompare(payload_name, "red", 3)) { 107 red_payload_type_ = payload_type; 108 payload = new ModuleRTPUtility::Payload; 109 memset(payload, 0, sizeof(*payload)); 110 payload->audio = false; 111 strncpy(payload->name, payload_name, RTP_PAYLOAD_NAME_SIZE - 1); 112 } else if (ModuleRTPUtility::StringCompare(payload_name, "ulpfec", 3)) { 113 ulpfec_payload_type_ = payload_type; 114 payload = new ModuleRTPUtility::Payload; 115 memset(payload, 0, sizeof(*payload)); 116 payload->audio = false; 117 strncpy(payload->name, payload_name, RTP_PAYLOAD_NAME_SIZE - 1); 118 } else { 119 *created_new_payload = true; 120 payload = rtp_payload_strategy_->CreatePayloadType( 121 payload_name, payload_type, frequency, channels, rate); 122 } 123 payload_type_map_[payload_type] = payload; 124 125 // Successful set of payload type, clear the value of last received payload 126 // type since it might mean something else. 127 last_received_payload_type_ = -1; 128 last_received_media_payload_type_ = -1; 129 return 0; 130 } 131 132 int32_t RTPPayloadRegistry::DeRegisterReceivePayload( 133 const int8_t payload_type) { 134 CriticalSectionScoped cs(crit_sect_.get()); 135 ModuleRTPUtility::PayloadTypeMap::iterator it = 136 payload_type_map_.find(payload_type); 137 assert(it != payload_type_map_.end()); 138 delete it->second; 139 payload_type_map_.erase(it); 140 return 0; 141 } 142 143 // There can't be several codecs with the same rate, frequency and channels 144 // for audio codecs, but there can for video. 145 // Always called from within a critical section. 146 void RTPPayloadRegistry::DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType( 147 const char payload_name[RTP_PAYLOAD_NAME_SIZE], 148 const size_t payload_name_length, 149 const uint32_t frequency, 150 const uint8_t channels, 151 const uint32_t rate) { 152 ModuleRTPUtility::PayloadTypeMap::iterator iterator = 153 payload_type_map_.begin(); 154 for (; iterator != payload_type_map_.end(); ++iterator) { 155 ModuleRTPUtility::Payload* payload = iterator->second; 156 size_t name_length = strlen(payload->name); 157 158 if (payload_name_length == name_length 159 && ModuleRTPUtility::StringCompare(payload->name, payload_name, 160 payload_name_length)) { 161 // We found the payload name in the list. 162 // If audio, check frequency and rate. 163 if (payload->audio) { 164 if (rtp_payload_strategy_->PayloadIsCompatible(*payload, frequency, 165 channels, rate)) { 166 // Remove old setting. 167 delete payload; 168 payload_type_map_.erase(iterator); 169 break; 170 } 171 } else if (ModuleRTPUtility::StringCompare(payload_name, "red", 3)) { 172 delete payload; 173 payload_type_map_.erase(iterator); 174 break; 175 } 176 } 177 } 178 } 179 180 int32_t RTPPayloadRegistry::ReceivePayloadType( 181 const char payload_name[RTP_PAYLOAD_NAME_SIZE], 182 const uint32_t frequency, 183 const uint8_t channels, 184 const uint32_t rate, 185 int8_t* payload_type) const { 186 assert(payload_type); 187 size_t payload_name_length = strlen(payload_name); 188 189 CriticalSectionScoped cs(crit_sect_.get()); 190 191 ModuleRTPUtility::PayloadTypeMap::const_iterator it = 192 payload_type_map_.begin(); 193 194 for (; it != payload_type_map_.end(); ++it) { 195 ModuleRTPUtility::Payload* payload = it->second; 196 assert(payload); 197 198 size_t name_length = strlen(payload->name); 199 if (payload_name_length == name_length && 200 ModuleRTPUtility::StringCompare( 201 payload->name, payload_name, payload_name_length)) { 202 // Name matches. 203 if (payload->audio) { 204 if (rate == 0) { 205 // [default] audio, check freq and channels. 206 if (payload->typeSpecific.Audio.frequency == frequency && 207 payload->typeSpecific.Audio.channels == channels) { 208 *payload_type = it->first; 209 return 0; 210 } 211 } else { 212 // Non-default audio, check freq, channels and rate. 213 if (payload->typeSpecific.Audio.frequency == frequency && 214 payload->typeSpecific.Audio.channels == channels && 215 payload->typeSpecific.Audio.rate == rate) { 216 // extra rate condition added 217 *payload_type = it->first; 218 return 0; 219 } 220 } 221 } else { 222 // Video. 223 *payload_type = it->first; 224 return 0; 225 } 226 } 227 } 228 return -1; 229 } 230 231 bool RTPPayloadRegistry::RtxEnabled() const { 232 CriticalSectionScoped cs(crit_sect_.get()); 233 return rtx_; 234 } 235 236 bool RTPPayloadRegistry::IsRtx(const RTPHeader& header) const { 237 CriticalSectionScoped cs(crit_sect_.get()); 238 return IsRtxInternal(header); 239 } 240 241 bool RTPPayloadRegistry::IsRtxInternal(const RTPHeader& header) const { 242 return rtx_ && ssrc_rtx_ == header.ssrc; 243 } 244 245 bool RTPPayloadRegistry::RestoreOriginalPacket(uint8_t** restored_packet, 246 const uint8_t* packet, 247 int* packet_length, 248 uint32_t original_ssrc, 249 const RTPHeader& header) const { 250 if (kRtxHeaderSize + header.headerLength > *packet_length) { 251 return false; 252 } 253 const uint8_t* rtx_header = packet + header.headerLength; 254 uint16_t original_sequence_number = (rtx_header[0] << 8) + rtx_header[1]; 255 256 // Copy the packet into the restored packet, except for the RTX header. 257 memcpy(*restored_packet, packet, header.headerLength); 258 memcpy(*restored_packet + header.headerLength, 259 packet + header.headerLength + kRtxHeaderSize, 260 *packet_length - header.headerLength - kRtxHeaderSize); 261 *packet_length -= kRtxHeaderSize; 262 263 // Replace the SSRC and the sequence number with the originals. 264 ModuleRTPUtility::AssignUWord16ToBuffer(*restored_packet + 2, 265 original_sequence_number); 266 ModuleRTPUtility::AssignUWord32ToBuffer(*restored_packet + 8, original_ssrc); 267 268 CriticalSectionScoped cs(crit_sect_.get()); 269 270 if (payload_type_rtx_ != -1) { 271 if (header.payloadType == payload_type_rtx_ && 272 incoming_payload_type_ != -1) { 273 (*restored_packet)[1] = static_cast<uint8_t>(incoming_payload_type_); 274 if (header.markerBit) { 275 (*restored_packet)[1] |= kRtpMarkerBitMask; // Marker bit is set. 276 } 277 } else { 278 LOG(LS_WARNING) << "Incorrect RTX configuration, dropping packet."; 279 return false; 280 } 281 } 282 return true; 283 } 284 285 void RTPPayloadRegistry::SetRtxSsrc(uint32_t ssrc) { 286 CriticalSectionScoped cs(crit_sect_.get()); 287 ssrc_rtx_ = ssrc; 288 rtx_ = true; 289 } 290 291 void RTPPayloadRegistry::SetRtxPayloadType(int payload_type) { 292 CriticalSectionScoped cs(crit_sect_.get()); 293 assert(payload_type >= 0); 294 payload_type_rtx_ = payload_type; 295 rtx_ = true; 296 } 297 298 bool RTPPayloadRegistry::IsRed(const RTPHeader& header) const { 299 CriticalSectionScoped cs(crit_sect_.get()); 300 return red_payload_type_ == header.payloadType; 301 } 302 303 bool RTPPayloadRegistry::IsEncapsulated(const RTPHeader& header) const { 304 return IsRed(header) || IsRtx(header); 305 } 306 307 bool RTPPayloadRegistry::GetPayloadSpecifics(uint8_t payload_type, 308 PayloadUnion* payload) const { 309 CriticalSectionScoped cs(crit_sect_.get()); 310 ModuleRTPUtility::PayloadTypeMap::const_iterator it = 311 payload_type_map_.find(payload_type); 312 313 // Check that this is a registered payload type. 314 if (it == payload_type_map_.end()) { 315 return false; 316 } 317 *payload = it->second->typeSpecific; 318 return true; 319 } 320 321 int RTPPayloadRegistry::GetPayloadTypeFrequency( 322 uint8_t payload_type) const { 323 ModuleRTPUtility::Payload* payload; 324 if (!PayloadTypeToPayload(payload_type, payload)) { 325 return -1; 326 } 327 CriticalSectionScoped cs(crit_sect_.get()); 328 return rtp_payload_strategy_->GetPayloadTypeFrequency(*payload); 329 } 330 331 bool RTPPayloadRegistry::PayloadTypeToPayload( 332 const uint8_t payload_type, 333 ModuleRTPUtility::Payload*& payload) const { 334 CriticalSectionScoped cs(crit_sect_.get()); 335 336 ModuleRTPUtility::PayloadTypeMap::const_iterator it = 337 payload_type_map_.find(payload_type); 338 339 // Check that this is a registered payload type. 340 if (it == payload_type_map_.end()) { 341 return false; 342 } 343 344 payload = it->second; 345 return true; 346 } 347 348 void RTPPayloadRegistry::SetIncomingPayloadType(const RTPHeader& header) { 349 CriticalSectionScoped cs(crit_sect_.get()); 350 if (!IsRtxInternal(header)) 351 incoming_payload_type_ = header.payloadType; 352 } 353 354 bool RTPPayloadRegistry::ReportMediaPayloadType(uint8_t media_payload_type) { 355 CriticalSectionScoped cs(crit_sect_.get()); 356 if (last_received_media_payload_type_ == media_payload_type) { 357 // Media type unchanged. 358 return true; 359 } 360 last_received_media_payload_type_ = media_payload_type; 361 return false; 362 } 363 364 class RTPPayloadAudioStrategy : public RTPPayloadStrategy { 365 public: 366 virtual bool CodecsMustBeUnique() const OVERRIDE { return true; } 367 368 virtual bool PayloadIsCompatible( 369 const ModuleRTPUtility::Payload& payload, 370 const uint32_t frequency, 371 const uint8_t channels, 372 const uint32_t rate) const OVERRIDE { 373 return 374 payload.audio && 375 payload.typeSpecific.Audio.frequency == frequency && 376 payload.typeSpecific.Audio.channels == channels && 377 (payload.typeSpecific.Audio.rate == rate || 378 payload.typeSpecific.Audio.rate == 0 || rate == 0); 379 } 380 381 virtual void UpdatePayloadRate( 382 ModuleRTPUtility::Payload* payload, 383 const uint32_t rate) const OVERRIDE { 384 payload->typeSpecific.Audio.rate = rate; 385 } 386 387 virtual ModuleRTPUtility::Payload* CreatePayloadType( 388 const char payloadName[RTP_PAYLOAD_NAME_SIZE], 389 const int8_t payloadType, 390 const uint32_t frequency, 391 const uint8_t channels, 392 const uint32_t rate) const OVERRIDE { 393 ModuleRTPUtility::Payload* payload = new ModuleRTPUtility::Payload; 394 payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0; 395 strncpy(payload->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1); 396 assert(frequency >= 1000); 397 payload->typeSpecific.Audio.frequency = frequency; 398 payload->typeSpecific.Audio.channels = channels; 399 payload->typeSpecific.Audio.rate = rate; 400 payload->audio = true; 401 return payload; 402 } 403 404 int GetPayloadTypeFrequency( 405 const ModuleRTPUtility::Payload& payload) const { 406 return payload.typeSpecific.Audio.frequency; 407 } 408 }; 409 410 class RTPPayloadVideoStrategy : public RTPPayloadStrategy { 411 public: 412 virtual bool CodecsMustBeUnique() const OVERRIDE { return false; } 413 414 virtual bool PayloadIsCompatible( 415 const ModuleRTPUtility::Payload& payload, 416 const uint32_t frequency, 417 const uint8_t channels, 418 const uint32_t rate) const OVERRIDE { 419 return !payload.audio; 420 } 421 422 virtual void UpdatePayloadRate( 423 ModuleRTPUtility::Payload* payload, 424 const uint32_t rate) const OVERRIDE { 425 payload->typeSpecific.Video.maxRate = rate; 426 } 427 428 virtual ModuleRTPUtility::Payload* CreatePayloadType( 429 const char payloadName[RTP_PAYLOAD_NAME_SIZE], 430 const int8_t payloadType, 431 const uint32_t frequency, 432 const uint8_t channels, 433 const uint32_t rate) const OVERRIDE { 434 RtpVideoCodecTypes videoType = kRtpVideoGeneric; 435 if (ModuleRTPUtility::StringCompare(payloadName, "VP8", 3)) { 436 videoType = kRtpVideoVp8; 437 } else if (ModuleRTPUtility::StringCompare(payloadName, "I420", 4)) { 438 videoType = kRtpVideoGeneric; 439 } else if (ModuleRTPUtility::StringCompare(payloadName, "ULPFEC", 6)) { 440 videoType = kRtpVideoNone; 441 } else { 442 videoType = kRtpVideoGeneric; 443 } 444 ModuleRTPUtility::Payload* payload = new ModuleRTPUtility::Payload; 445 446 payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0; 447 strncpy(payload->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1); 448 payload->typeSpecific.Video.videoCodecType = videoType; 449 payload->typeSpecific.Video.maxRate = rate; 450 payload->audio = false; 451 return payload; 452 } 453 454 int GetPayloadTypeFrequency( 455 const ModuleRTPUtility::Payload& payload) const { 456 return kVideoPayloadTypeFrequency; 457 } 458 }; 459 460 RTPPayloadStrategy* RTPPayloadStrategy::CreateStrategy( 461 const bool handling_audio) { 462 if (handling_audio) { 463 return new RTPPayloadAudioStrategy(); 464 } else { 465 return new RTPPayloadVideoStrategy(); 466 } 467 } 468 469 } // namespace webrtc 470