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     RtpUtility::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   RtpUtility::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     RtpUtility::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         RtpUtility::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   RtpUtility::Payload* payload = NULL;
    104 
    105   // Save the RED payload type. Used in both audio and video.
    106   if (RtpUtility::StringCompare(payload_name, "red", 3)) {
    107     red_payload_type_ = payload_type;
    108     payload = new RtpUtility::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 (RtpUtility::StringCompare(payload_name, "ulpfec", 3)) {
    113     ulpfec_payload_type_ = payload_type;
    114     payload = new RtpUtility::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   RtpUtility::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   RtpUtility::PayloadTypeMap::iterator iterator = payload_type_map_.begin();
    153   for (; iterator != payload_type_map_.end(); ++iterator) {
    154     RtpUtility::Payload* payload = iterator->second;
    155     size_t name_length = strlen(payload->name);
    156 
    157     if (payload_name_length == name_length &&
    158         RtpUtility::StringCompare(
    159             payload->name, payload_name, payload_name_length)) {
    160       // We found the payload name in the list.
    161       // If audio, check frequency and rate.
    162       if (payload->audio) {
    163         if (rtp_payload_strategy_->PayloadIsCompatible(*payload, frequency,
    164                                                        channels, rate)) {
    165           // Remove old setting.
    166           delete payload;
    167           payload_type_map_.erase(iterator);
    168           break;
    169         }
    170       } else if (RtpUtility::StringCompare(payload_name, "red", 3)) {
    171         delete payload;
    172         payload_type_map_.erase(iterator);
    173         break;
    174       }
    175     }
    176   }
    177 }
    178 
    179 int32_t RTPPayloadRegistry::ReceivePayloadType(
    180     const char payload_name[RTP_PAYLOAD_NAME_SIZE],
    181     const uint32_t frequency,
    182     const uint8_t channels,
    183     const uint32_t rate,
    184     int8_t* payload_type) const {
    185   assert(payload_type);
    186   size_t payload_name_length = strlen(payload_name);
    187 
    188   CriticalSectionScoped cs(crit_sect_.get());
    189 
    190   RtpUtility::PayloadTypeMap::const_iterator it = payload_type_map_.begin();
    191 
    192   for (; it != payload_type_map_.end(); ++it) {
    193     RtpUtility::Payload* payload = it->second;
    194     assert(payload);
    195 
    196     size_t name_length = strlen(payload->name);
    197     if (payload_name_length == name_length &&
    198         RtpUtility::StringCompare(
    199             payload->name, payload_name, payload_name_length)) {
    200       // Name matches.
    201       if (payload->audio) {
    202         if (rate == 0) {
    203           // [default] audio, check freq and channels.
    204           if (payload->typeSpecific.Audio.frequency == frequency &&
    205               payload->typeSpecific.Audio.channels == channels) {
    206             *payload_type = it->first;
    207             return 0;
    208           }
    209         } else {
    210           // Non-default audio, check freq, channels and rate.
    211           if (payload->typeSpecific.Audio.frequency == frequency &&
    212               payload->typeSpecific.Audio.channels == channels &&
    213               payload->typeSpecific.Audio.rate == rate) {
    214             // extra rate condition added
    215             *payload_type = it->first;
    216             return 0;
    217           }
    218         }
    219       } else {
    220         // Video.
    221         *payload_type = it->first;
    222         return 0;
    223       }
    224     }
    225   }
    226   return -1;
    227 }
    228 
    229 bool RTPPayloadRegistry::RtxEnabled() const {
    230   CriticalSectionScoped cs(crit_sect_.get());
    231   return rtx_;
    232 }
    233 
    234 bool RTPPayloadRegistry::IsRtx(const RTPHeader& header) const {
    235   CriticalSectionScoped cs(crit_sect_.get());
    236   return IsRtxInternal(header);
    237 }
    238 
    239 bool RTPPayloadRegistry::IsRtxInternal(const RTPHeader& header) const {
    240   return rtx_ && ssrc_rtx_ == header.ssrc;
    241 }
    242 
    243 bool RTPPayloadRegistry::RestoreOriginalPacket(uint8_t** restored_packet,
    244                                                const uint8_t* packet,
    245                                                int* packet_length,
    246                                                uint32_t original_ssrc,
    247                                                const RTPHeader& header) const {
    248   if (kRtxHeaderSize + header.headerLength > *packet_length) {
    249     return false;
    250   }
    251   const uint8_t* rtx_header = packet + header.headerLength;
    252   uint16_t original_sequence_number = (rtx_header[0] << 8) + rtx_header[1];
    253 
    254   // Copy the packet into the restored packet, except for the RTX header.
    255   memcpy(*restored_packet, packet, header.headerLength);
    256   memcpy(*restored_packet + header.headerLength,
    257          packet + header.headerLength + kRtxHeaderSize,
    258          *packet_length - header.headerLength - kRtxHeaderSize);
    259   *packet_length -= kRtxHeaderSize;
    260 
    261   // Replace the SSRC and the sequence number with the originals.
    262   RtpUtility::AssignUWord16ToBuffer(*restored_packet + 2,
    263                                     original_sequence_number);
    264   RtpUtility::AssignUWord32ToBuffer(*restored_packet + 8, original_ssrc);
    265 
    266   CriticalSectionScoped cs(crit_sect_.get());
    267 
    268   if (payload_type_rtx_ != -1) {
    269     if (header.payloadType == payload_type_rtx_ &&
    270         incoming_payload_type_ != -1) {
    271       (*restored_packet)[1] = static_cast<uint8_t>(incoming_payload_type_);
    272       if (header.markerBit) {
    273         (*restored_packet)[1] |= kRtpMarkerBitMask;  // Marker bit is set.
    274       }
    275     } else {
    276       LOG(LS_WARNING) << "Incorrect RTX configuration, dropping packet.";
    277       return false;
    278     }
    279   }
    280   return true;
    281 }
    282 
    283 void RTPPayloadRegistry::SetRtxSsrc(uint32_t ssrc) {
    284   CriticalSectionScoped cs(crit_sect_.get());
    285   ssrc_rtx_ = ssrc;
    286   rtx_ = true;
    287 }
    288 
    289 void RTPPayloadRegistry::SetRtxPayloadType(int payload_type) {
    290   CriticalSectionScoped cs(crit_sect_.get());
    291   assert(payload_type >= 0);
    292   payload_type_rtx_ = payload_type;
    293   rtx_ = true;
    294 }
    295 
    296 bool RTPPayloadRegistry::IsRed(const RTPHeader& header) const {
    297   CriticalSectionScoped cs(crit_sect_.get());
    298   return red_payload_type_ == header.payloadType;
    299 }
    300 
    301 bool RTPPayloadRegistry::IsEncapsulated(const RTPHeader& header) const {
    302   return IsRed(header) || IsRtx(header);
    303 }
    304 
    305 bool RTPPayloadRegistry::GetPayloadSpecifics(uint8_t payload_type,
    306                                              PayloadUnion* payload) const {
    307   CriticalSectionScoped cs(crit_sect_.get());
    308   RtpUtility::PayloadTypeMap::const_iterator it =
    309       payload_type_map_.find(payload_type);
    310 
    311   // Check that this is a registered payload type.
    312   if (it == payload_type_map_.end()) {
    313     return false;
    314   }
    315   *payload = it->second->typeSpecific;
    316   return true;
    317 }
    318 
    319 int RTPPayloadRegistry::GetPayloadTypeFrequency(
    320     uint8_t payload_type) const {
    321   RtpUtility::Payload* payload;
    322   if (!PayloadTypeToPayload(payload_type, payload)) {
    323     return -1;
    324   }
    325   CriticalSectionScoped cs(crit_sect_.get());
    326   return rtp_payload_strategy_->GetPayloadTypeFrequency(*payload);
    327 }
    328 
    329 bool RTPPayloadRegistry::PayloadTypeToPayload(
    330     const uint8_t payload_type,
    331     RtpUtility::Payload*& payload) const {
    332   CriticalSectionScoped cs(crit_sect_.get());
    333 
    334   RtpUtility::PayloadTypeMap::const_iterator it =
    335       payload_type_map_.find(payload_type);
    336 
    337   // Check that this is a registered payload type.
    338   if (it == payload_type_map_.end()) {
    339     return false;
    340   }
    341 
    342   payload = it->second;
    343   return true;
    344 }
    345 
    346 void RTPPayloadRegistry::SetIncomingPayloadType(const RTPHeader& header) {
    347   CriticalSectionScoped cs(crit_sect_.get());
    348   if (!IsRtxInternal(header))
    349     incoming_payload_type_ = header.payloadType;
    350 }
    351 
    352 bool RTPPayloadRegistry::ReportMediaPayloadType(uint8_t media_payload_type) {
    353   CriticalSectionScoped cs(crit_sect_.get());
    354   if (last_received_media_payload_type_ == media_payload_type) {
    355     // Media type unchanged.
    356     return true;
    357   }
    358   last_received_media_payload_type_ = media_payload_type;
    359   return false;
    360 }
    361 
    362 class RTPPayloadAudioStrategy : public RTPPayloadStrategy {
    363  public:
    364   virtual bool CodecsMustBeUnique() const OVERRIDE { return true; }
    365 
    366   virtual bool PayloadIsCompatible(const RtpUtility::Payload& payload,
    367                                    const uint32_t frequency,
    368                                    const uint8_t channels,
    369                                    const uint32_t rate) const OVERRIDE {
    370     return
    371         payload.audio &&
    372         payload.typeSpecific.Audio.frequency == frequency &&
    373         payload.typeSpecific.Audio.channels == channels &&
    374         (payload.typeSpecific.Audio.rate == rate ||
    375             payload.typeSpecific.Audio.rate == 0 || rate == 0);
    376   }
    377 
    378   virtual void UpdatePayloadRate(RtpUtility::Payload* payload,
    379                                  const uint32_t rate) const OVERRIDE {
    380     payload->typeSpecific.Audio.rate = rate;
    381   }
    382 
    383   virtual RtpUtility::Payload* CreatePayloadType(
    384       const char payloadName[RTP_PAYLOAD_NAME_SIZE],
    385       const int8_t payloadType,
    386       const uint32_t frequency,
    387       const uint8_t channels,
    388       const uint32_t rate) const OVERRIDE {
    389     RtpUtility::Payload* payload = new RtpUtility::Payload;
    390     payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
    391     strncpy(payload->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1);
    392     assert(frequency >= 1000);
    393     payload->typeSpecific.Audio.frequency = frequency;
    394     payload->typeSpecific.Audio.channels = channels;
    395     payload->typeSpecific.Audio.rate = rate;
    396     payload->audio = true;
    397     return payload;
    398   }
    399 
    400   int GetPayloadTypeFrequency(const RtpUtility::Payload& payload) const {
    401     return payload.typeSpecific.Audio.frequency;
    402   }
    403 };
    404 
    405 class RTPPayloadVideoStrategy : public RTPPayloadStrategy {
    406  public:
    407   virtual bool CodecsMustBeUnique() const OVERRIDE { return false; }
    408 
    409   virtual bool PayloadIsCompatible(const RtpUtility::Payload& payload,
    410                                    const uint32_t frequency,
    411                                    const uint8_t channels,
    412                                    const uint32_t rate) const OVERRIDE {
    413     return !payload.audio;
    414   }
    415 
    416   virtual void UpdatePayloadRate(RtpUtility::Payload* payload,
    417                                  const uint32_t rate) const OVERRIDE {
    418     payload->typeSpecific.Video.maxRate = rate;
    419   }
    420 
    421   virtual RtpUtility::Payload* CreatePayloadType(
    422       const char payloadName[RTP_PAYLOAD_NAME_SIZE],
    423       const int8_t payloadType,
    424       const uint32_t frequency,
    425       const uint8_t channels,
    426       const uint32_t rate) const OVERRIDE {
    427     RtpVideoCodecTypes videoType = kRtpVideoGeneric;
    428     if (RtpUtility::StringCompare(payloadName, "VP8", 3)) {
    429       videoType = kRtpVideoVp8;
    430     } else if (RtpUtility::StringCompare(payloadName, "H264", 4)) {
    431       videoType = kRtpVideoH264;
    432     } else if (RtpUtility::StringCompare(payloadName, "I420", 4)) {
    433       videoType = kRtpVideoGeneric;
    434     } else if (RtpUtility::StringCompare(payloadName, "ULPFEC", 6)) {
    435       videoType = kRtpVideoNone;
    436     } else {
    437       videoType = kRtpVideoGeneric;
    438     }
    439     RtpUtility::Payload* payload = new RtpUtility::Payload;
    440 
    441     payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
    442     strncpy(payload->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1);
    443     payload->typeSpecific.Video.videoCodecType = videoType;
    444     payload->typeSpecific.Video.maxRate = rate;
    445     payload->audio = false;
    446     return payload;
    447   }
    448 
    449   int GetPayloadTypeFrequency(const RtpUtility::Payload& payload) const {
    450     return kVideoPayloadTypeFrequency;
    451   }
    452 };
    453 
    454 RTPPayloadStrategy* RTPPayloadStrategy::CreateStrategy(
    455     const bool handling_audio) {
    456   if (handling_audio) {
    457     return new RTPPayloadAudioStrategy();
    458   } else {
    459     return new RTPPayloadVideoStrategy();
    460   }
    461 }
    462 
    463 }  // namespace webrtc
    464