LCOV - code coverage report
Current view: top level - media/webrtc/trunk/webrtc/modules/rtp_rtcp/source - rtp_payload_registry.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 0 207 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 28 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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/include/rtp_payload_registry.h"
      12             : 
      13             : #include <algorithm>
      14             : 
      15             : #include "webrtc/base/checks.h"
      16             : #include "webrtc/base/logging.h"
      17             : #include "webrtc/base/stringutils.h"
      18             : #include "webrtc/common_types.h"
      19             : #include "webrtc/modules/rtp_rtcp/source/byte_io.h"
      20             : 
      21             : namespace webrtc {
      22             : 
      23             : namespace {
      24             : 
      25           0 : bool PayloadIsCompatible(const RtpUtility::Payload& payload,
      26             :                          const CodecInst& audio_codec) {
      27           0 :   if (!payload.audio)
      28           0 :     return false;
      29           0 :   if (_stricmp(payload.name, audio_codec.plname) != 0)
      30           0 :     return false;
      31           0 :   const AudioPayload& audio_payload = payload.typeSpecific.Audio;
      32           0 :   return audio_payload.frequency == static_cast<uint32_t>(audio_codec.plfreq) &&
      33           0 :          audio_payload.channels == audio_codec.channels;
      34             : }
      35             : 
      36           0 : bool PayloadIsCompatible(const RtpUtility::Payload& payload,
      37             :                          const VideoCodec& video_codec) {
      38           0 :   if (payload.audio || _stricmp(payload.name, video_codec.plName) != 0)
      39           0 :     return false;
      40             :   // For H264, profiles must match as well.
      41           0 :   if (video_codec.codecType == kVideoCodecH264) {
      42           0 :     return video_codec.H264().profile ==
      43           0 :            payload.typeSpecific.Video.h264_profile;
      44             :   }
      45           0 :   return true;
      46             : }
      47             : 
      48           0 : RtpUtility::Payload CreatePayloadType(const CodecInst& audio_codec) {
      49             :   RtpUtility::Payload payload;
      50           0 :   payload.name[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
      51           0 :   strncpy(payload.name, audio_codec.plname, RTP_PAYLOAD_NAME_SIZE - 1);
      52           0 :   RTC_DCHECK_GE(audio_codec.plfreq, 1000);
      53           0 :   payload.typeSpecific.Audio.frequency = audio_codec.plfreq;
      54           0 :   payload.typeSpecific.Audio.channels = audio_codec.channels;
      55           0 :   payload.typeSpecific.Audio.rate = 0;
      56           0 :   payload.audio = true;
      57           0 :   return payload;
      58             : }
      59             : 
      60           0 : RtpVideoCodecTypes ConvertToRtpVideoCodecType(VideoCodecType type) {
      61           0 :   switch (type) {
      62             :     case kVideoCodecVP8:
      63           0 :       return kRtpVideoVp8;
      64             :     case kVideoCodecVP9:
      65           0 :       return kRtpVideoVp9;
      66             :     case kVideoCodecH264:
      67           0 :       return kRtpVideoH264;
      68             :     case kVideoCodecRED:
      69             :     case kVideoCodecULPFEC:
      70           0 :       return kRtpVideoNone;
      71             :     default:
      72           0 :       return kRtpVideoGeneric;
      73             :   }
      74             : }
      75             : 
      76           0 : RtpUtility::Payload CreatePayloadType(const VideoCodec& video_codec) {
      77             :   RtpUtility::Payload payload;
      78           0 :   payload.name[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
      79           0 :   strncpy(payload.name, video_codec.plName, RTP_PAYLOAD_NAME_SIZE - 1);
      80           0 :   payload.typeSpecific.Video.videoCodecType =
      81           0 :       ConvertToRtpVideoCodecType(video_codec.codecType);
      82           0 :   if (video_codec.codecType == kVideoCodecH264)
      83           0 :     payload.typeSpecific.Video.h264_profile = video_codec.H264().profile;
      84           0 :   payload.audio = false;
      85           0 :   return payload;
      86             : }
      87             : 
      88           0 : bool IsPayloadTypeValid(int8_t payload_type) {
      89           0 :   assert(payload_type >= 0);
      90             : 
      91             :   // Sanity check.
      92           0 :   switch (payload_type) {
      93             :     // Reserved payload types to avoid RTCP conflicts when marker bit is set.
      94             :     case 64:        //  192 Full INTRA-frame request.
      95             :     case 72:        //  200 Sender report.
      96             :     case 73:        //  201 Receiver report.
      97             :     case 74:        //  202 Source description.
      98             :     case 75:        //  203 Goodbye.
      99             :     case 76:        //  204 Application-defined.
     100             :     case 77:        //  205 Transport layer FB message.
     101             :     case 78:        //  206 Payload-specific FB message.
     102             :     case 79:        //  207 Extended report.
     103           0 :       LOG(LS_ERROR) << "Can't register invalid receiver payload type: "
     104           0 :                     << payload_type;
     105           0 :       return false;
     106             :     default:
     107           0 :       return true;
     108             :   }
     109             : }
     110             : 
     111             : }  // namespace
     112             : 
     113           0 : RTPPayloadRegistry::RTPPayloadRegistry()
     114             :     : incoming_payload_type_(-1),
     115             :       last_received_payload_type_(-1),
     116             :       last_received_media_payload_type_(-1),
     117             :       rtx_(false),
     118           0 :       ssrc_rtx_(0) {}
     119             : 
     120             : RTPPayloadRegistry::~RTPPayloadRegistry() = default;
     121             : 
     122           0 : int32_t RTPPayloadRegistry::RegisterReceivePayload(const CodecInst& audio_codec,
     123             :                                                    bool* created_new_payload) {
     124           0 :   *created_new_payload = false;
     125           0 :   if (!IsPayloadTypeValid(audio_codec.pltype))
     126           0 :     return -1;
     127             : 
     128           0 :   rtc::CritScope cs(&crit_sect_);
     129             : 
     130           0 :   auto it = payload_type_map_.find(audio_codec.pltype);
     131           0 :   if (it != payload_type_map_.end()) {
     132             :     // We already use this payload type. Check if it's the same as we already
     133             :     // have. If same, ignore sending an error.
     134           0 :     if (PayloadIsCompatible(it->second, audio_codec)) {
     135           0 :       it->second.typeSpecific.Audio.rate = 0;
     136           0 :       return 0;
     137             :     }
     138           0 :     LOG(LS_ERROR) << "Payload type already registered: " << audio_codec.pltype;
     139           0 :     return -1;
     140             :   }
     141             : 
     142             :   // Audio codecs must be unique.
     143           0 :   DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType(audio_codec);
     144             : 
     145           0 :   payload_type_map_[audio_codec.pltype] = CreatePayloadType(audio_codec);
     146           0 :   *created_new_payload = true;
     147             : 
     148             :   // Successful set of payload type, clear the value of last received payload
     149             :   // type since it might mean something else.
     150           0 :   last_received_payload_type_ = -1;
     151           0 :   last_received_media_payload_type_ = -1;
     152           0 :   return 0;
     153             : }
     154             : 
     155           0 : int32_t RTPPayloadRegistry::RegisterReceivePayload(
     156             :     const VideoCodec& video_codec) {
     157           0 :   if (!IsPayloadTypeValid(video_codec.plType))
     158           0 :     return -1;
     159             : 
     160           0 :   rtc::CritScope cs(&crit_sect_);
     161             : 
     162           0 :   auto it = payload_type_map_.find(video_codec.plType);
     163           0 :   if (it != payload_type_map_.end()) {
     164             :     // We already use this payload type. Check if it's the same as we already
     165             :     // have. If same, ignore sending an error.
     166           0 :     if (PayloadIsCompatible(it->second, video_codec))
     167           0 :       return 0;
     168           0 :     LOG(LS_ERROR) << "Payload type already registered: "
     169           0 :                   << static_cast<int>(video_codec.plType);
     170           0 :     return -1;
     171             :   }
     172             : 
     173           0 :   payload_type_map_[video_codec.plType] = CreatePayloadType(video_codec);
     174             : 
     175             :   // Successful set of payload type, clear the value of last received payload
     176             :   // type since it might mean something else.
     177           0 :   last_received_payload_type_ = -1;
     178           0 :   last_received_media_payload_type_ = -1;
     179           0 :   return 0;
     180             : }
     181             : 
     182           0 : int32_t RTPPayloadRegistry::DeRegisterReceivePayload(
     183             :     const int8_t payload_type) {
     184           0 :   rtc::CritScope cs(&crit_sect_);
     185           0 :   payload_type_map_.erase(payload_type);
     186           0 :   return 0;
     187             : }
     188             : 
     189             : // There can't be several codecs with the same rate, frequency and channels
     190             : // for audio codecs, but there can for video.
     191             : // Always called from within a critical section.
     192           0 : void RTPPayloadRegistry::DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType(
     193             :     const CodecInst& audio_codec) {
     194           0 :   for (auto iterator = payload_type_map_.begin();
     195           0 :        iterator != payload_type_map_.end(); ++iterator) {
     196           0 :     if (PayloadIsCompatible(iterator->second, audio_codec)) {
     197             :       // Remove old setting.
     198           0 :       payload_type_map_.erase(iterator);
     199           0 :       break;
     200             :     }
     201             :   }
     202           0 : }
     203             : 
     204           0 : int32_t RTPPayloadRegistry::ReceivePayloadType(const CodecInst& audio_codec,
     205             :                                                int8_t* payload_type) const {
     206           0 :   assert(payload_type);
     207           0 :   rtc::CritScope cs(&crit_sect_);
     208             : 
     209           0 :   for (const auto& it : payload_type_map_) {
     210           0 :     if (PayloadIsCompatible(it.second, audio_codec)) {
     211           0 :       *payload_type = it.first;
     212           0 :       return 0;
     213             :     }
     214             :   }
     215           0 :   return -1;
     216             : }
     217             : 
     218           0 : int32_t RTPPayloadRegistry::ReceivePayloadType(const VideoCodec& video_codec,
     219             :                                                int8_t* payload_type) const {
     220           0 :   assert(payload_type);
     221           0 :   rtc::CritScope cs(&crit_sect_);
     222             : 
     223           0 :   for (const auto& it : payload_type_map_) {
     224           0 :     if (PayloadIsCompatible(it.second, video_codec)) {
     225           0 :       *payload_type = it.first;
     226           0 :       return 0;
     227             :     }
     228             :   }
     229           0 :   return -1;
     230             : }
     231             : 
     232           0 : bool RTPPayloadRegistry::RtxEnabled() const {
     233           0 :   rtc::CritScope cs(&crit_sect_);
     234           0 :   return rtx_;
     235             : }
     236             : 
     237           0 : bool RTPPayloadRegistry::IsRtx(const RTPHeader& header) const {
     238           0 :   rtc::CritScope cs(&crit_sect_);
     239           0 :   return IsRtxInternal(header);
     240             : }
     241             : 
     242           0 : bool RTPPayloadRegistry::IsRtxInternal(const RTPHeader& header) const {
     243           0 :   return rtx_ && ssrc_rtx_ == header.ssrc;
     244             : }
     245             : 
     246           0 : bool RTPPayloadRegistry::RestoreOriginalPacket(uint8_t* restored_packet,
     247             :                                                const uint8_t* packet,
     248             :                                                size_t* packet_length,
     249             :                                                uint32_t original_ssrc,
     250             :                                                const RTPHeader& header) {
     251           0 :   if (kRtxHeaderSize + header.headerLength + header.paddingLength >
     252           0 :       *packet_length) {
     253           0 :     return false;
     254             :   }
     255           0 :   const uint8_t* rtx_header = packet + header.headerLength;
     256           0 :   uint16_t original_sequence_number = (rtx_header[0] << 8) + rtx_header[1];
     257             : 
     258             :   // Copy the packet into the restored packet, except for the RTX header.
     259           0 :   memcpy(restored_packet, packet, header.headerLength);
     260           0 :   memcpy(restored_packet + header.headerLength,
     261           0 :          packet + header.headerLength + kRtxHeaderSize,
     262           0 :          *packet_length - header.headerLength - kRtxHeaderSize);
     263           0 :   *packet_length -= kRtxHeaderSize;
     264             : 
     265             :   // Replace the SSRC and the sequence number with the originals.
     266           0 :   ByteWriter<uint16_t>::WriteBigEndian(restored_packet + 2,
     267           0 :                                        original_sequence_number);
     268           0 :   ByteWriter<uint32_t>::WriteBigEndian(restored_packet + 8, original_ssrc);
     269             : 
     270           0 :   rtc::CritScope cs(&crit_sect_);
     271           0 :   if (!rtx_)
     272           0 :     return true;
     273             : 
     274           0 :   auto apt_mapping = rtx_payload_type_map_.find(header.payloadType);
     275           0 :   if (apt_mapping == rtx_payload_type_map_.end()) {
     276             :     // No associated payload type found. Warn, unless we have already done so.
     277           0 :     if (payload_types_with_suppressed_warnings_.find(header.payloadType) ==
     278           0 :         payload_types_with_suppressed_warnings_.end()) {
     279           0 :       LOG(LS_WARNING)
     280             :           << "No RTX associated payload type mapping was available; "
     281             :              "not able to restore original packet from RTX packet "
     282           0 :              "with payload type: "
     283           0 :           << static_cast<int>(header.payloadType) << ". "
     284           0 :           << "Suppressing further warnings for this payload type.";
     285           0 :       payload_types_with_suppressed_warnings_.insert(header.payloadType);
     286             :     }
     287           0 :     return false;
     288             :   }
     289           0 :   restored_packet[1] = static_cast<uint8_t>(apt_mapping->second);
     290           0 :   if (header.markerBit) {
     291           0 :     restored_packet[1] |= kRtpMarkerBitMask;  // Marker bit is set.
     292             :   }
     293           0 :   return true;
     294             : }
     295             : 
     296           0 : void RTPPayloadRegistry::SetRtxSsrc(uint32_t ssrc) {
     297           0 :   rtc::CritScope cs(&crit_sect_);
     298           0 :   ssrc_rtx_ = ssrc;
     299           0 :   rtx_ = true;
     300           0 : }
     301             : 
     302           0 : bool RTPPayloadRegistry::GetRtxSsrc(uint32_t* ssrc) const {
     303           0 :   rtc::CritScope cs(&crit_sect_);
     304           0 :   *ssrc = ssrc_rtx_;
     305           0 :   return rtx_;
     306             : }
     307             : 
     308           0 : void RTPPayloadRegistry::SetRtxPayloadType(int payload_type,
     309             :                                            int associated_payload_type) {
     310           0 :   rtc::CritScope cs(&crit_sect_);
     311           0 :   if (payload_type < 0) {
     312           0 :     LOG(LS_ERROR) << "Invalid RTX payload type: " << payload_type;
     313           0 :     return;
     314             :   }
     315             : 
     316           0 :   rtx_payload_type_map_[payload_type] = associated_payload_type;
     317           0 :   rtx_ = true;
     318             : }
     319             : 
     320           0 : bool RTPPayloadRegistry::IsRed(const RTPHeader& header) const {
     321           0 :   rtc::CritScope cs(&crit_sect_);
     322           0 :   auto it = payload_type_map_.find(header.payloadType);
     323           0 :   return it != payload_type_map_.end() && _stricmp(it->second.name, "red") == 0;
     324             : }
     325             : 
     326           0 : bool RTPPayloadRegistry::IsEncapsulated(const RTPHeader& header) const {
     327           0 :   return IsRed(header) || IsRtx(header);
     328             : }
     329             : 
     330           0 : bool RTPPayloadRegistry::GetPayloadSpecifics(uint8_t payload_type,
     331             :                                              PayloadUnion* payload) const {
     332           0 :   rtc::CritScope cs(&crit_sect_);
     333           0 :   auto it = payload_type_map_.find(payload_type);
     334             : 
     335             :   // Check that this is a registered payload type.
     336           0 :   if (it == payload_type_map_.end()) {
     337           0 :     return false;
     338             :   }
     339           0 :   *payload = it->second.typeSpecific;
     340           0 :   return true;
     341             : }
     342             : 
     343           0 : int RTPPayloadRegistry::GetPayloadTypeFrequency(
     344             :     uint8_t payload_type) const {
     345           0 :   const RtpUtility::Payload* payload = PayloadTypeToPayload(payload_type);
     346           0 :   if (!payload) {
     347           0 :     return -1;
     348             :   }
     349           0 :   rtc::CritScope cs(&crit_sect_);
     350           0 :   return payload->audio ? payload->typeSpecific.Audio.frequency
     351           0 :                         : kVideoPayloadTypeFrequency;
     352             : }
     353             : 
     354           0 : const RtpUtility::Payload* RTPPayloadRegistry::PayloadTypeToPayload(
     355             :     uint8_t payload_type) const {
     356           0 :   rtc::CritScope cs(&crit_sect_);
     357             : 
     358           0 :   auto it = payload_type_map_.find(payload_type);
     359             : 
     360             :   // Check that this is a registered payload type.
     361           0 :   if (it == payload_type_map_.end()) {
     362           0 :     return nullptr;
     363             :   }
     364             : 
     365           0 :   return &it->second;
     366             : }
     367             : 
     368           0 : void RTPPayloadRegistry::SetIncomingPayloadType(const RTPHeader& header) {
     369           0 :   rtc::CritScope cs(&crit_sect_);
     370           0 :   if (!IsRtxInternal(header))
     371           0 :     incoming_payload_type_ = header.payloadType;
     372           0 : }
     373             : 
     374           0 : bool RTPPayloadRegistry::ReportMediaPayloadType(uint8_t media_payload_type) {
     375           0 :   rtc::CritScope cs(&crit_sect_);
     376           0 :   if (last_received_media_payload_type_ == media_payload_type) {
     377             :     // Media type unchanged.
     378           0 :     return true;
     379             :   }
     380           0 :   last_received_media_payload_type_ = media_payload_type;
     381           0 :   return false;
     382             : }
     383             : 
     384             : // Returns -1 if a payload with name |payload_name| is not registered.
     385           0 : int8_t RTPPayloadRegistry::GetPayloadTypeWithName(
     386             :     const char* payload_name) const {
     387           0 :   rtc::CritScope cs(&crit_sect_);
     388           0 :   for (const auto& it : payload_type_map_) {
     389           0 :     if (_stricmp(it.second.name, payload_name) == 0)
     390           0 :       return it.first;
     391             :   }
     392           0 :   return -1;
     393             : }
     394             : 
     395             : }  // namespace webrtc

Generated by: LCOV version 1.13