Home | History | Annotate | Download | only in source
      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