Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| 11 #include "webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h" | 11 #include "webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h" |
| 12 | 12 |
| 13 #include "webrtc/base/logging.h" | 13 #include "webrtc/base/logging.h" |
| 14 #include "webrtc/common_types.h" | 14 #include "webrtc/common_types.h" |
| 15 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" | 15 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" |
| 16 | 16 |
| 17 namespace webrtc { | 17 namespace webrtc { |
| 18 | 18 |
| 19 RTPPayloadRegistry::RTPPayloadRegistry(RTPPayloadStrategy* rtp_payload_strategy) | 19 namespace { |
| 20 : rtp_payload_strategy_(rtp_payload_strategy), | 20 |
| 21 red_payload_type_(-1), | 21 bool PayloadIsCompatible(const RtpUtility::Payload& payload, |
| 22 ulpfec_payload_type_(-1), | 22 const CodecInst& audio_codec) { |
| 23 incoming_payload_type_(-1), | 23 if (!payload.audio) |
| 24 return false; | |
| 25 if (!RtpUtility::StringCompare(payload.name, audio_codec.plname)) | |
| 26 return false; | |
| 27 const AudioPayload& audio_payload = payload.typeSpecific.Audio; | |
| 28 const uint32_t rate = std::max(0, audio_codec.rate); | |
| 29 return audio_payload.frequency == static_cast<uint32_t>(audio_codec.plfreq) && | |
| 30 audio_payload.channels == audio_codec.channels && | |
| 31 (audio_payload.rate == rate || audio_payload.rate == 0 || rate == 0); | |
| 32 } | |
| 33 | |
| 34 bool PayloadIsCompatible(const RtpUtility::Payload& payload, | |
| 35 const VideoCodec& video_codec) { | |
| 36 return !payload.audio && | |
| 37 RtpUtility::StringCompare(payload.name, video_codec.plName); | |
| 38 } | |
| 39 | |
| 40 RtpUtility::Payload CreatePayloadType(const CodecInst& audio_codec) { | |
| 41 RtpUtility::Payload payload; | |
| 42 payload.name[RTP_PAYLOAD_NAME_SIZE - 1] = 0; | |
| 43 strncpy(payload.name, audio_codec.plname, RTP_PAYLOAD_NAME_SIZE - 1); | |
| 44 assert(audio_codec.plfreq >= 1000); | |
|
danilchap
2016/11/23 19:06:18
RTC_DCHECK_GE(audio_codec.plfreq, 1000);
(and #inc
magjed_webrtc
2016/11/24 12:20:39
Done. This logic is copy-pasted from line 427 if y
| |
| 45 payload.typeSpecific.Audio.frequency = audio_codec.plfreq; | |
| 46 payload.typeSpecific.Audio.channels = audio_codec.channels; | |
| 47 payload.typeSpecific.Audio.rate = std::max(0, audio_codec.rate); | |
| 48 payload.audio = true; | |
| 49 return payload; | |
| 50 } | |
| 51 | |
| 52 RtpVideoCodecTypes ConvertToRtpVideoCodecType(VideoCodecType type) { | |
| 53 switch (type) { | |
| 54 case kVideoCodecVP8: | |
| 55 return kRtpVideoVp8; | |
| 56 case kVideoCodecVP9: | |
| 57 return kRtpVideoVp9; | |
| 58 case kVideoCodecH264: | |
| 59 return kRtpVideoH264; | |
| 60 case kVideoCodecRED: | |
| 61 case kVideoCodecULPFEC: | |
| 62 return kRtpVideoNone; | |
| 63 default: | |
| 64 return kRtpVideoGeneric; | |
| 65 } | |
| 66 } | |
| 67 | |
| 68 RtpUtility::Payload CreatePayloadType(const VideoCodec& video_codec) { | |
| 69 RtpUtility::Payload payload; | |
| 70 payload.name[RTP_PAYLOAD_NAME_SIZE - 1] = 0; | |
| 71 strncpy(payload.name, video_codec.plName, RTP_PAYLOAD_NAME_SIZE - 1); | |
| 72 payload.typeSpecific.Video.videoCodecType = | |
| 73 ConvertToRtpVideoCodecType(video_codec.codecType); | |
| 74 payload.audio = false; | |
| 75 return payload; | |
| 76 } | |
| 77 | |
| 78 } // anonymous namespace | |
| 79 | |
| 80 RTPPayloadRegistry::RTPPayloadRegistry() | |
| 81 : incoming_payload_type_(-1), | |
| 24 last_received_payload_type_(-1), | 82 last_received_payload_type_(-1), |
| 25 last_received_media_payload_type_(-1), | 83 last_received_media_payload_type_(-1), |
| 26 rtx_(false), | 84 rtx_(false), |
| 27 ssrc_rtx_(0) {} | 85 ssrc_rtx_(0) {} |
| 28 | 86 |
| 29 RTPPayloadRegistry::~RTPPayloadRegistry() { | 87 bool IsPayloadTypeValid(int8_t payload_type) { |
| 30 while (!payload_type_map_.empty()) { | |
| 31 RtpUtility::PayloadTypeMap::iterator it = payload_type_map_.begin(); | |
| 32 delete it->second; | |
| 33 payload_type_map_.erase(it); | |
| 34 } | |
| 35 } | |
| 36 | |
| 37 int32_t RTPPayloadRegistry::RegisterReceivePayload(const CodecInst& audio_codec, | |
| 38 bool* created_new_payload) { | |
| 39 return RegisterReceivePayload( | |
| 40 audio_codec.plname, audio_codec.pltype, audio_codec.plfreq, | |
| 41 audio_codec.channels, std::max(0, audio_codec.rate), created_new_payload); | |
| 42 } | |
| 43 | |
| 44 int32_t RTPPayloadRegistry::RegisterReceivePayload( | |
| 45 const VideoCodec& video_codec) { | |
| 46 bool dummy_created_new_payload; | |
| 47 return RegisterReceivePayload(video_codec.plName, video_codec.plType, | |
| 48 kVideoPayloadTypeFrequency, 0 /* channels */, | |
| 49 0 /* rate */, &dummy_created_new_payload); | |
| 50 } | |
| 51 | |
| 52 int32_t RTPPayloadRegistry::RegisterReceivePayload( | |
| 53 const char* const payload_name, | |
| 54 const int8_t payload_type, | |
| 55 const uint32_t frequency, | |
| 56 const size_t channels, | |
| 57 const uint32_t rate, | |
| 58 bool* created_new_payload) { | |
| 59 assert(payload_type >= 0); | 88 assert(payload_type >= 0); |
| 60 assert(payload_name); | |
| 61 *created_new_payload = false; | |
| 62 | 89 |
| 63 // Sanity check. | 90 // Sanity check. |
| 64 switch (payload_type) { | 91 switch (payload_type) { |
| 65 // Reserved payload types to avoid RTCP conflicts when marker bit is set. | 92 // Reserved payload types to avoid RTCP conflicts when marker bit is set. |
| 66 case 64: // 192 Full INTRA-frame request. | 93 case 64: // 192 Full INTRA-frame request. |
| 67 case 72: // 200 Sender report. | 94 case 72: // 200 Sender report. |
| 68 case 73: // 201 Receiver report. | 95 case 73: // 201 Receiver report. |
| 69 case 74: // 202 Source description. | 96 case 74: // 202 Source description. |
| 70 case 75: // 203 Goodbye. | 97 case 75: // 203 Goodbye. |
| 71 case 76: // 204 Application-defined. | 98 case 76: // 204 Application-defined. |
| 72 case 77: // 205 Transport layer FB message. | 99 case 77: // 205 Transport layer FB message. |
| 73 case 78: // 206 Payload-specific FB message. | 100 case 78: // 206 Payload-specific FB message. |
| 74 case 79: // 207 Extended report. | 101 case 79: // 207 Extended report. |
| 75 LOG(LS_ERROR) << "Can't register invalid receiver payload type: " | 102 LOG(LS_ERROR) << "Can't register invalid receiver payload type: " |
| 76 << payload_type; | 103 << payload_type; |
| 77 return -1; | 104 return false; |
| 78 default: | 105 default: |
| 79 break; | 106 return true; |
| 80 } | 107 } |
| 108 } | |
| 81 | 109 |
| 82 size_t payload_name_length = strlen(payload_name); | 110 int32_t RTPPayloadRegistry::RegisterReceivePayload(const CodecInst& audio_codec, |
| 111 bool* created_new_payload) { | |
| 112 *created_new_payload = false; | |
| 113 if (!IsPayloadTypeValid(audio_codec.pltype)) | |
| 114 return -1; | |
| 115 | |
| 116 const uint32_t rate = std::max(0, audio_codec.rate); | |
|
danilchap
2016/11/23 19:06:18
while you recalculate rate, you do not set it back
magjed_webrtc
2016/11/24 12:20:39
Yes, that's why I recalculate the rate from audio_
danilchap
2016/11/24 13:24:36
oops, missed that, not a problem then.
may be then
magjed_webrtc
2016/11/24 14:29:29
Done.
| |
| 83 | 117 |
| 84 rtc::CritScope cs(&crit_sect_); | 118 rtc::CritScope cs(&crit_sect_); |
| 85 | 119 |
| 86 RtpUtility::PayloadTypeMap::iterator it = | 120 auto it = payload_type_map_.find(audio_codec.pltype); |
| 87 payload_type_map_.find(payload_type); | |
| 88 | |
| 89 if (it != payload_type_map_.end()) { | 121 if (it != payload_type_map_.end()) { |
| 90 // We already use this payload type. | 122 // We already use this payload type. Check if it's the same as we already |
| 91 RtpUtility::Payload* payload = it->second; | 123 // have. If same, ignore sending an error. |
| 92 | 124 if (PayloadIsCompatible(it->second, audio_codec)) { |
| 93 assert(payload); | 125 it->second.typeSpecific.Audio.rate = rate; |
| 94 | 126 return 0; |
| 95 size_t name_length = strlen(payload->name); | |
| 96 | |
| 97 // Check if it's the same as we already have. | |
| 98 // If same, ignore sending an error. | |
| 99 if (payload_name_length == name_length && | |
| 100 RtpUtility::StringCompare( | |
| 101 payload->name, payload_name, payload_name_length)) { | |
| 102 if (rtp_payload_strategy_->PayloadIsCompatible(*payload, frequency, | |
| 103 channels, rate)) { | |
| 104 rtp_payload_strategy_->UpdatePayloadRate(payload, rate); | |
| 105 return 0; | |
| 106 } | |
| 107 } | 127 } |
| 108 LOG(LS_ERROR) << "Payload type already registered: " | 128 LOG(LS_ERROR) << "Payload type already registered: " << audio_codec.pltype; |
| 109 << static_cast<int>(payload_type); | |
| 110 return -1; | 129 return -1; |
| 111 } | 130 } |
| 112 | 131 |
| 113 if (rtp_payload_strategy_->CodecsMustBeUnique()) { | 132 // Audio codecs must be unique. |
| 114 DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType( | 133 DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType(audio_codec); |
| 115 payload_name, payload_name_length, frequency, channels, rate); | |
| 116 } | |
| 117 | 134 |
| 118 RtpUtility::Payload* payload = rtp_payload_strategy_->CreatePayloadType( | 135 payload_type_map_[audio_codec.pltype] = CreatePayloadType(audio_codec); |
| 119 payload_name, payload_type, frequency, channels, rate); | |
| 120 | |
| 121 payload_type_map_[payload_type] = payload; | |
| 122 *created_new_payload = true; | 136 *created_new_payload = true; |
| 123 | 137 |
| 124 if (RtpUtility::StringCompare(payload_name, "red", 3)) { | |
| 125 red_payload_type_ = payload_type; | |
| 126 } else if (RtpUtility::StringCompare(payload_name, "ulpfec", 6)) { | |
| 127 ulpfec_payload_type_ = payload_type; | |
| 128 } | |
| 129 | |
| 130 // Successful set of payload type, clear the value of last received payload | 138 // Successful set of payload type, clear the value of last received payload |
| 131 // type since it might mean something else. | 139 // type since it might mean something else. |
| 132 last_received_payload_type_ = -1; | 140 last_received_payload_type_ = -1; |
| 141 last_received_media_payload_type_ = -1; | |
| 142 return 0; | |
| 143 } | |
| 144 | |
| 145 int32_t RTPPayloadRegistry::RegisterReceivePayload( | |
| 146 const VideoCodec& video_codec) { | |
| 147 if (!IsPayloadTypeValid(video_codec.plType)) | |
| 148 return -1; | |
| 149 | |
| 150 rtc::CritScope cs(&crit_sect_); | |
| 151 | |
| 152 auto it = payload_type_map_.find(video_codec.plType); | |
| 153 if (it != payload_type_map_.end()) { | |
| 154 // We already use this payload type. Check if it's the same as we already | |
| 155 // have. If same, ignore sending an error. | |
| 156 if (PayloadIsCompatible(it->second, video_codec)) | |
| 157 return 0; | |
| 158 LOG(LS_ERROR) << "Payload type already registered: " | |
| 159 << static_cast<int>(video_codec.plType); | |
| 160 return -1; | |
| 161 } | |
| 162 | |
| 163 payload_type_map_[video_codec.plType] = CreatePayloadType(video_codec); | |
| 164 | |
| 165 // Successful set of payload type, clear the value of last received payload | |
| 166 // type since it might mean something else. | |
| 167 last_received_payload_type_ = -1; | |
| 133 last_received_media_payload_type_ = -1; | 168 last_received_media_payload_type_ = -1; |
| 134 return 0; | 169 return 0; |
| 135 } | 170 } |
| 136 | 171 |
| 137 int32_t RTPPayloadRegistry::DeRegisterReceivePayload( | 172 int32_t RTPPayloadRegistry::DeRegisterReceivePayload( |
| 138 const int8_t payload_type) { | 173 const int8_t payload_type) { |
| 139 rtc::CritScope cs(&crit_sect_); | 174 rtc::CritScope cs(&crit_sect_); |
| 140 RtpUtility::PayloadTypeMap::iterator it = | 175 payload_type_map_.erase(payload_type); |
| 141 payload_type_map_.find(payload_type); | |
| 142 assert(it != payload_type_map_.end()); | |
| 143 delete it->second; | |
| 144 payload_type_map_.erase(it); | |
| 145 return 0; | 176 return 0; |
| 146 } | 177 } |
| 147 | 178 |
| 148 // There can't be several codecs with the same rate, frequency and channels | 179 // There can't be several codecs with the same rate, frequency and channels |
| 149 // for audio codecs, but there can for video. | 180 // for audio codecs, but there can for video. |
| 150 // Always called from within a critical section. | 181 // Always called from within a critical section. |
| 151 void RTPPayloadRegistry::DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType( | 182 void RTPPayloadRegistry::DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType( |
| 152 const char* const payload_name, | 183 const CodecInst& audio_codec) { |
| 153 const size_t payload_name_length, | 184 for (auto iterator = payload_type_map_.begin(); |
| 154 const uint32_t frequency, | 185 iterator != payload_type_map_.end(); ++iterator) { |
| 155 const size_t channels, | 186 if (PayloadIsCompatible(iterator->second, audio_codec)) { |
| 156 const uint32_t rate) { | 187 // Remove old setting. |
| 157 RtpUtility::PayloadTypeMap::iterator iterator = payload_type_map_.begin(); | 188 payload_type_map_.erase(iterator); |
| 158 for (; iterator != payload_type_map_.end(); ++iterator) { | 189 break; |
| 159 RtpUtility::Payload* payload = iterator->second; | |
| 160 size_t name_length = strlen(payload->name); | |
| 161 | |
| 162 if (payload_name_length == name_length && | |
| 163 RtpUtility::StringCompare( | |
| 164 payload->name, payload_name, payload_name_length)) { | |
| 165 // We found the payload name in the list. | |
| 166 // If audio, check frequency and rate. | |
| 167 if (payload->audio) { | |
| 168 if (rtp_payload_strategy_->PayloadIsCompatible(*payload, frequency, | |
| 169 channels, rate)) { | |
| 170 // Remove old setting. | |
| 171 delete payload; | |
| 172 payload_type_map_.erase(iterator); | |
| 173 break; | |
| 174 } | |
| 175 } else if (RtpUtility::StringCompare(payload_name, "red", 3)) { | |
| 176 delete payload; | |
| 177 payload_type_map_.erase(iterator); | |
| 178 break; | |
| 179 } | |
| 180 } | 190 } |
| 181 } | 191 } |
| 182 } | 192 } |
| 183 | 193 |
| 184 int32_t RTPPayloadRegistry::ReceivePayloadType(const CodecInst& audio_codec, | 194 int32_t RTPPayloadRegistry::ReceivePayloadType(const CodecInst& audio_codec, |
| 185 int8_t* payload_type) const { | 195 int8_t* payload_type) const { |
| 186 return ReceivePayloadType(audio_codec.plname, audio_codec.plfreq, | 196 assert(payload_type); |
| 187 audio_codec.channels, std::max(0, audio_codec.rate), | 197 rtc::CritScope cs(&crit_sect_); |
| 188 payload_type); | 198 |
| 199 for (const auto& it : payload_type_map_) { | |
| 200 if (PayloadIsCompatible(it.second, audio_codec)) { | |
| 201 *payload_type = it.first; | |
| 202 return 0; | |
| 203 } | |
| 204 } | |
| 205 return -1; | |
| 189 } | 206 } |
| 190 | 207 |
| 191 int32_t RTPPayloadRegistry::ReceivePayloadType(const VideoCodec& video_codec, | 208 int32_t RTPPayloadRegistry::ReceivePayloadType(const VideoCodec& video_codec, |
| 192 int8_t* payload_type) const { | 209 int8_t* payload_type) const { |
| 193 return ReceivePayloadType(video_codec.plName, kVideoPayloadTypeFrequency, | |
| 194 0 /* channels */, 0 /* rate */, payload_type); | |
| 195 } | |
| 196 | |
| 197 int32_t RTPPayloadRegistry::ReceivePayloadType(const char* const payload_name, | |
| 198 const uint32_t frequency, | |
| 199 const size_t channels, | |
| 200 const uint32_t rate, | |
| 201 int8_t* payload_type) const { | |
| 202 assert(payload_type); | 210 assert(payload_type); |
| 203 size_t payload_name_length = strlen(payload_name); | |
| 204 | |
| 205 rtc::CritScope cs(&crit_sect_); | 211 rtc::CritScope cs(&crit_sect_); |
| 206 | 212 |
| 207 RtpUtility::PayloadTypeMap::const_iterator it = payload_type_map_.begin(); | 213 for (const auto& it : payload_type_map_) { |
| 208 | 214 if (PayloadIsCompatible(it.second, video_codec)) { |
| 209 for (; it != payload_type_map_.end(); ++it) { | 215 *payload_type = it.first; |
| 210 RtpUtility::Payload* payload = it->second; | 216 return 0; |
| 211 assert(payload); | |
| 212 | |
| 213 size_t name_length = strlen(payload->name); | |
| 214 if (payload_name_length == name_length && | |
| 215 RtpUtility::StringCompare( | |
| 216 payload->name, payload_name, payload_name_length)) { | |
| 217 // Name matches. | |
| 218 if (payload->audio) { | |
| 219 if (rate == 0) { | |
|
danilchap
2016/11/23 19:06:18
if (stored->Audio.rate == 0 && received->audio_cod
magjed_webrtc
2016/11/24 12:20:39
Yes, this is true, thanks for reviewing so careful
| |
| 220 // [default] audio, check freq and channels. | |
| 221 if (payload->typeSpecific.Audio.frequency == frequency && | |
| 222 payload->typeSpecific.Audio.channels == channels) { | |
| 223 *payload_type = it->first; | |
| 224 return 0; | |
| 225 } | |
| 226 } else { | |
| 227 // Non-default audio, check freq, channels and rate. | |
| 228 if (payload->typeSpecific.Audio.frequency == frequency && | |
| 229 payload->typeSpecific.Audio.channels == channels && | |
| 230 payload->typeSpecific.Audio.rate == rate) { | |
| 231 // extra rate condition added | |
| 232 *payload_type = it->first; | |
| 233 return 0; | |
| 234 } | |
| 235 } | |
| 236 } else { | |
| 237 // Video. | |
| 238 *payload_type = it->first; | |
| 239 return 0; | |
| 240 } | |
| 241 } | 217 } |
| 242 } | 218 } |
| 243 return -1; | 219 return -1; |
| 244 } | 220 } |
| 245 | 221 |
| 246 bool RTPPayloadRegistry::RtxEnabled() const { | 222 bool RTPPayloadRegistry::RtxEnabled() const { |
| 247 rtc::CritScope cs(&crit_sect_); | 223 rtc::CritScope cs(&crit_sect_); |
| 248 return rtx_; | 224 return rtx_; |
| 249 } | 225 } |
| 250 | 226 |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 326 LOG(LS_ERROR) << "Invalid RTX payload type: " << payload_type; | 302 LOG(LS_ERROR) << "Invalid RTX payload type: " << payload_type; |
| 327 return; | 303 return; |
| 328 } | 304 } |
| 329 | 305 |
| 330 rtx_payload_type_map_[payload_type] = associated_payload_type; | 306 rtx_payload_type_map_[payload_type] = associated_payload_type; |
| 331 rtx_ = true; | 307 rtx_ = true; |
| 332 } | 308 } |
| 333 | 309 |
| 334 bool RTPPayloadRegistry::IsRed(const RTPHeader& header) const { | 310 bool RTPPayloadRegistry::IsRed(const RTPHeader& header) const { |
| 335 rtc::CritScope cs(&crit_sect_); | 311 rtc::CritScope cs(&crit_sect_); |
| 336 return red_payload_type_ == header.payloadType; | 312 auto it = payload_type_map_.find(header.payloadType); |
| 313 return it != payload_type_map_.end() && | |
| 314 RtpUtility::StringCompare(it->second.name, "red"); | |
| 337 } | 315 } |
| 338 | 316 |
| 339 bool RTPPayloadRegistry::IsEncapsulated(const RTPHeader& header) const { | 317 bool RTPPayloadRegistry::IsEncapsulated(const RTPHeader& header) const { |
| 340 return IsRed(header) || IsRtx(header); | 318 return IsRed(header) || IsRtx(header); |
| 341 } | 319 } |
| 342 | 320 |
| 343 bool RTPPayloadRegistry::GetPayloadSpecifics(uint8_t payload_type, | 321 bool RTPPayloadRegistry::GetPayloadSpecifics(uint8_t payload_type, |
| 344 PayloadUnion* payload) const { | 322 PayloadUnion* payload) const { |
| 345 rtc::CritScope cs(&crit_sect_); | 323 rtc::CritScope cs(&crit_sect_); |
| 346 RtpUtility::PayloadTypeMap::const_iterator it = | 324 auto it = payload_type_map_.find(payload_type); |
| 347 payload_type_map_.find(payload_type); | |
| 348 | 325 |
| 349 // Check that this is a registered payload type. | 326 // Check that this is a registered payload type. |
| 350 if (it == payload_type_map_.end()) { | 327 if (it == payload_type_map_.end()) { |
| 351 return false; | 328 return false; |
| 352 } | 329 } |
| 353 *payload = it->second->typeSpecific; | 330 *payload = it->second.typeSpecific; |
| 354 return true; | 331 return true; |
| 355 } | 332 } |
| 356 | 333 |
| 357 int RTPPayloadRegistry::GetPayloadTypeFrequency( | 334 int RTPPayloadRegistry::GetPayloadTypeFrequency( |
| 358 uint8_t payload_type) const { | 335 uint8_t payload_type) const { |
| 359 const RtpUtility::Payload* payload = PayloadTypeToPayload(payload_type); | 336 const RtpUtility::Payload* payload = PayloadTypeToPayload(payload_type); |
| 360 if (!payload) { | 337 if (!payload) { |
| 361 return -1; | 338 return -1; |
| 362 } | 339 } |
| 363 rtc::CritScope cs(&crit_sect_); | 340 rtc::CritScope cs(&crit_sect_); |
| 364 return rtp_payload_strategy_->GetPayloadTypeFrequency(*payload); | 341 return payload->audio ? payload->typeSpecific.Audio.frequency |
| 342 : kVideoPayloadTypeFrequency; | |
| 365 } | 343 } |
| 366 | 344 |
| 367 const RtpUtility::Payload* RTPPayloadRegistry::PayloadTypeToPayload( | 345 const RtpUtility::Payload* RTPPayloadRegistry::PayloadTypeToPayload( |
| 368 uint8_t payload_type) const { | 346 uint8_t payload_type) const { |
| 369 rtc::CritScope cs(&crit_sect_); | 347 rtc::CritScope cs(&crit_sect_); |
| 370 | 348 |
| 371 RtpUtility::PayloadTypeMap::const_iterator it = | 349 auto it = payload_type_map_.find(payload_type); |
| 372 payload_type_map_.find(payload_type); | |
| 373 | 350 |
| 374 // Check that this is a registered payload type. | 351 // Check that this is a registered payload type. |
| 375 if (it == payload_type_map_.end()) { | 352 if (it == payload_type_map_.end()) { |
| 376 return nullptr; | 353 return nullptr; |
| 377 } | 354 } |
| 378 | 355 |
| 379 return it->second; | 356 return &it->second; |
| 380 } | 357 } |
| 381 | 358 |
| 382 void RTPPayloadRegistry::SetIncomingPayloadType(const RTPHeader& header) { | 359 void RTPPayloadRegistry::SetIncomingPayloadType(const RTPHeader& header) { |
| 383 rtc::CritScope cs(&crit_sect_); | 360 rtc::CritScope cs(&crit_sect_); |
| 384 if (!IsRtxInternal(header)) | 361 if (!IsRtxInternal(header)) |
| 385 incoming_payload_type_ = header.payloadType; | 362 incoming_payload_type_ = header.payloadType; |
| 386 } | 363 } |
| 387 | 364 |
| 388 bool RTPPayloadRegistry::ReportMediaPayloadType(uint8_t media_payload_type) { | 365 bool RTPPayloadRegistry::ReportMediaPayloadType(uint8_t media_payload_type) { |
| 389 rtc::CritScope cs(&crit_sect_); | 366 rtc::CritScope cs(&crit_sect_); |
| 390 if (last_received_media_payload_type_ == media_payload_type) { | 367 if (last_received_media_payload_type_ == media_payload_type) { |
| 391 // Media type unchanged. | 368 // Media type unchanged. |
| 392 return true; | 369 return true; |
| 393 } | 370 } |
| 394 last_received_media_payload_type_ = media_payload_type; | 371 last_received_media_payload_type_ = media_payload_type; |
| 395 return false; | 372 return false; |
| 396 } | 373 } |
| 397 | 374 |
| 398 class RTPPayloadAudioStrategy : public RTPPayloadStrategy { | 375 // Returns -1 if a payload with name |payload_name| is not registered. |
| 399 public: | 376 int8_t RTPPayloadRegistry::GetPayloadTypeWithName( |
| 400 bool CodecsMustBeUnique() const override { return true; } | 377 const char* payload_name) const { |
| 401 | 378 rtc::CritScope cs(&crit_sect_); |
| 402 bool PayloadIsCompatible(const RtpUtility::Payload& payload, | 379 for (const auto& it : payload_type_map_) { |
| 403 const uint32_t frequency, | 380 if (RtpUtility::StringCompare(it.second.name, payload_name)) |
| 404 const size_t channels, | 381 return it.first; |
| 405 const uint32_t rate) const override { | |
| 406 return | |
| 407 payload.audio && | |
| 408 payload.typeSpecific.Audio.frequency == frequency && | |
| 409 payload.typeSpecific.Audio.channels == channels && | |
| 410 (payload.typeSpecific.Audio.rate == rate || | |
| 411 payload.typeSpecific.Audio.rate == 0 || rate == 0); | |
| 412 } | 382 } |
| 413 | 383 return -1; |
| 414 void UpdatePayloadRate(RtpUtility::Payload* payload, | |
| 415 const uint32_t rate) const override { | |
| 416 payload->typeSpecific.Audio.rate = rate; | |
| 417 } | |
| 418 | |
| 419 RtpUtility::Payload* CreatePayloadType(const char* const payloadName, | |
| 420 const int8_t payloadType, | |
| 421 const uint32_t frequency, | |
| 422 const size_t channels, | |
| 423 const uint32_t rate) const override { | |
| 424 RtpUtility::Payload* payload = new RtpUtility::Payload; | |
| 425 payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0; | |
| 426 strncpy(payload->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1); | |
| 427 assert(frequency >= 1000); | |
| 428 payload->typeSpecific.Audio.frequency = frequency; | |
| 429 payload->typeSpecific.Audio.channels = channels; | |
| 430 payload->typeSpecific.Audio.rate = rate; | |
| 431 payload->audio = true; | |
| 432 return payload; | |
| 433 } | |
| 434 | |
| 435 int GetPayloadTypeFrequency( | |
| 436 const RtpUtility::Payload& payload) const override { | |
| 437 return payload.typeSpecific.Audio.frequency; | |
| 438 } | |
| 439 }; | |
| 440 | |
| 441 class RTPPayloadVideoStrategy : public RTPPayloadStrategy { | |
| 442 public: | |
| 443 bool CodecsMustBeUnique() const override { return false; } | |
| 444 | |
| 445 bool PayloadIsCompatible(const RtpUtility::Payload& payload, | |
| 446 const uint32_t frequency, | |
| 447 const size_t channels, | |
| 448 const uint32_t rate) const override { | |
| 449 return !payload.audio; | |
| 450 } | |
| 451 | |
| 452 void UpdatePayloadRate(RtpUtility::Payload* payload, | |
| 453 const uint32_t rate) const override {} | |
| 454 | |
| 455 RtpUtility::Payload* CreatePayloadType(const char* const payloadName, | |
| 456 const int8_t payloadType, | |
| 457 const uint32_t frequency, | |
| 458 const size_t channels, | |
| 459 const uint32_t rate) const override { | |
| 460 RtpVideoCodecTypes videoType = kRtpVideoGeneric; | |
| 461 | |
| 462 if (RtpUtility::StringCompare(payloadName, "VP8", 3)) { | |
| 463 videoType = kRtpVideoVp8; | |
| 464 } else if (RtpUtility::StringCompare(payloadName, "VP9", 3)) { | |
| 465 videoType = kRtpVideoVp9; | |
| 466 } else if (RtpUtility::StringCompare(payloadName, "H264", 4)) { | |
| 467 videoType = kRtpVideoH264; | |
| 468 } else if (RtpUtility::StringCompare(payloadName, "I420", 4)) { | |
| 469 videoType = kRtpVideoGeneric; | |
| 470 } else if (RtpUtility::StringCompare(payloadName, "ULPFEC", 6) || | |
| 471 RtpUtility::StringCompare(payloadName, "RED", 3)) { | |
| 472 videoType = kRtpVideoNone; | |
| 473 } else { | |
| 474 videoType = kRtpVideoGeneric; | |
| 475 } | |
| 476 RtpUtility::Payload* payload = new RtpUtility::Payload; | |
| 477 | |
| 478 payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0; | |
| 479 strncpy(payload->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1); | |
| 480 payload->typeSpecific.Video.videoCodecType = videoType; | |
| 481 payload->audio = false; | |
| 482 return payload; | |
| 483 } | |
| 484 | |
| 485 int GetPayloadTypeFrequency( | |
| 486 const RtpUtility::Payload& payload) const override { | |
| 487 return kVideoPayloadTypeFrequency; | |
| 488 } | |
| 489 }; | |
| 490 | |
| 491 RTPPayloadStrategy* RTPPayloadStrategy::CreateStrategy( | |
| 492 const bool handling_audio) { | |
| 493 if (handling_audio) { | |
| 494 return new RTPPayloadAudioStrategy(); | |
| 495 } else { | |
| 496 return new RTPPayloadVideoStrategy(); | |
| 497 } | |
| 498 } | 384 } |
| 499 | 385 |
| 500 } // namespace webrtc | 386 } // namespace webrtc |
| OLD | NEW |