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 <algorithm> | |
14 | |
15 #include "webrtc/base/checks.h" | |
16 #include "webrtc/base/logging.h" | 13 #include "webrtc/base/logging.h" |
17 #include "webrtc/base/stringutils.h" | |
18 #include "webrtc/common_types.h" | 14 #include "webrtc/common_types.h" |
19 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" | 15 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" |
20 | 16 |
21 namespace webrtc { | 17 namespace webrtc { |
22 | 18 |
23 namespace { | 19 RTPPayloadRegistry::RTPPayloadRegistry(RTPPayloadStrategy* rtp_payload_strategy) |
| 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 ssrc_rtx_(0) {} |
24 | 28 |
25 bool PayloadIsCompatible(const RtpUtility::Payload& payload, | 29 RTPPayloadRegistry::~RTPPayloadRegistry() { |
26 const CodecInst& audio_codec) { | 30 while (!payload_type_map_.empty()) { |
27 if (!payload.audio) | 31 RtpUtility::PayloadTypeMap::iterator it = payload_type_map_.begin(); |
28 return false; | 32 delete it->second; |
29 if (_stricmp(payload.name, audio_codec.plname) != 0) | 33 payload_type_map_.erase(it); |
30 return false; | |
31 const AudioPayload& audio_payload = payload.typeSpecific.Audio; | |
32 const uint32_t rate = std::max(0, audio_codec.rate); | |
33 return audio_payload.frequency == static_cast<uint32_t>(audio_codec.plfreq) && | |
34 audio_payload.channels == audio_codec.channels && | |
35 (audio_payload.rate == rate || audio_payload.rate == 0 || rate == 0); | |
36 } | |
37 | |
38 bool PayloadIsCompatible(const RtpUtility::Payload& payload, | |
39 const VideoCodec& video_codec) { | |
40 return !payload.audio && _stricmp(payload.name, video_codec.plName) == 0; | |
41 } | |
42 | |
43 RtpUtility::Payload CreatePayloadType(const CodecInst& audio_codec) { | |
44 RtpUtility::Payload payload; | |
45 payload.name[RTP_PAYLOAD_NAME_SIZE - 1] = 0; | |
46 strncpy(payload.name, audio_codec.plname, RTP_PAYLOAD_NAME_SIZE - 1); | |
47 RTC_DCHECK_GE(audio_codec.plfreq, 1000); | |
48 payload.typeSpecific.Audio.frequency = audio_codec.plfreq; | |
49 payload.typeSpecific.Audio.channels = audio_codec.channels; | |
50 payload.typeSpecific.Audio.rate = std::max(0, audio_codec.rate); | |
51 payload.audio = true; | |
52 return payload; | |
53 } | |
54 | |
55 RtpVideoCodecTypes ConvertToRtpVideoCodecType(VideoCodecType type) { | |
56 switch (type) { | |
57 case kVideoCodecVP8: | |
58 return kRtpVideoVp8; | |
59 case kVideoCodecVP9: | |
60 return kRtpVideoVp9; | |
61 case kVideoCodecH264: | |
62 return kRtpVideoH264; | |
63 case kVideoCodecRED: | |
64 case kVideoCodecULPFEC: | |
65 return kRtpVideoNone; | |
66 default: | |
67 return kRtpVideoGeneric; | |
68 } | 34 } |
69 } | 35 } |
70 | 36 |
71 RtpUtility::Payload CreatePayloadType(const VideoCodec& video_codec) { | 37 int32_t RTPPayloadRegistry::RegisterReceivePayload(const CodecInst& audio_codec, |
72 RtpUtility::Payload payload; | 38 bool* created_new_payload) { |
73 payload.name[RTP_PAYLOAD_NAME_SIZE - 1] = 0; | 39 return RegisterReceivePayload( |
74 strncpy(payload.name, video_codec.plName, RTP_PAYLOAD_NAME_SIZE - 1); | 40 audio_codec.plname, audio_codec.pltype, audio_codec.plfreq, |
75 payload.typeSpecific.Video.videoCodecType = | 41 audio_codec.channels, std::max(0, audio_codec.rate), created_new_payload); |
76 ConvertToRtpVideoCodecType(video_codec.codecType); | |
77 payload.audio = false; | |
78 return payload; | |
79 } | 42 } |
80 | 43 |
81 bool IsPayloadTypeValid(int8_t payload_type) { | 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) { |
82 assert(payload_type >= 0); | 59 assert(payload_type >= 0); |
| 60 assert(payload_name); |
| 61 *created_new_payload = false; |
83 | 62 |
84 // Sanity check. | 63 // Sanity check. |
85 switch (payload_type) { | 64 switch (payload_type) { |
86 // Reserved payload types to avoid RTCP conflicts when marker bit is set. | 65 // Reserved payload types to avoid RTCP conflicts when marker bit is set. |
87 case 64: // 192 Full INTRA-frame request. | 66 case 64: // 192 Full INTRA-frame request. |
88 case 72: // 200 Sender report. | 67 case 72: // 200 Sender report. |
89 case 73: // 201 Receiver report. | 68 case 73: // 201 Receiver report. |
90 case 74: // 202 Source description. | 69 case 74: // 202 Source description. |
91 case 75: // 203 Goodbye. | 70 case 75: // 203 Goodbye. |
92 case 76: // 204 Application-defined. | 71 case 76: // 204 Application-defined. |
93 case 77: // 205 Transport layer FB message. | 72 case 77: // 205 Transport layer FB message. |
94 case 78: // 206 Payload-specific FB message. | 73 case 78: // 206 Payload-specific FB message. |
95 case 79: // 207 Extended report. | 74 case 79: // 207 Extended report. |
96 LOG(LS_ERROR) << "Can't register invalid receiver payload type: " | 75 LOG(LS_ERROR) << "Can't register invalid receiver payload type: " |
97 << payload_type; | 76 << payload_type; |
98 return false; | 77 return -1; |
99 default: | 78 default: |
100 return true; | 79 break; |
101 } | 80 } |
102 } | |
103 | 81 |
104 } // namespace | 82 size_t payload_name_length = strlen(payload_name); |
105 | |
106 RTPPayloadRegistry::RTPPayloadRegistry() | |
107 : incoming_payload_type_(-1), | |
108 last_received_payload_type_(-1), | |
109 last_received_media_payload_type_(-1), | |
110 rtx_(false), | |
111 ssrc_rtx_(0) {} | |
112 | |
113 RTPPayloadRegistry::~RTPPayloadRegistry() = default; | |
114 | |
115 int32_t RTPPayloadRegistry::RegisterReceivePayload(const CodecInst& audio_codec, | |
116 bool* created_new_payload) { | |
117 *created_new_payload = false; | |
118 if (!IsPayloadTypeValid(audio_codec.pltype)) | |
119 return -1; | |
120 | 83 |
121 rtc::CritScope cs(&crit_sect_); | 84 rtc::CritScope cs(&crit_sect_); |
122 | 85 |
123 auto it = payload_type_map_.find(audio_codec.pltype); | 86 RtpUtility::PayloadTypeMap::iterator it = |
| 87 payload_type_map_.find(payload_type); |
| 88 |
124 if (it != payload_type_map_.end()) { | 89 if (it != payload_type_map_.end()) { |
125 // We already use this payload type. Check if it's the same as we already | 90 // We already use this payload type. |
126 // have. If same, ignore sending an error. | 91 RtpUtility::Payload* payload = it->second; |
127 if (PayloadIsCompatible(it->second, audio_codec)) { | 92 |
128 it->second.typeSpecific.Audio.rate = std::max(0, audio_codec.rate); | 93 assert(payload); |
129 return 0; | 94 |
| 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 } |
130 } | 107 } |
131 LOG(LS_ERROR) << "Payload type already registered: " << audio_codec.pltype; | 108 LOG(LS_ERROR) << "Payload type already registered: " |
| 109 << static_cast<int>(payload_type); |
132 return -1; | 110 return -1; |
133 } | 111 } |
134 | 112 |
135 // Audio codecs must be unique. | 113 if (rtp_payload_strategy_->CodecsMustBeUnique()) { |
136 DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType(audio_codec); | 114 DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType( |
| 115 payload_name, payload_name_length, frequency, channels, rate); |
| 116 } |
137 | 117 |
138 payload_type_map_[audio_codec.pltype] = CreatePayloadType(audio_codec); | 118 RtpUtility::Payload* payload = rtp_payload_strategy_->CreatePayloadType( |
| 119 payload_name, payload_type, frequency, channels, rate); |
| 120 |
| 121 payload_type_map_[payload_type] = payload; |
139 *created_new_payload = true; | 122 *created_new_payload = true; |
140 | 123 |
| 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 |
141 // Successful set of payload type, clear the value of last received payload | 130 // Successful set of payload type, clear the value of last received payload |
142 // type since it might mean something else. | 131 // type since it might mean something else. |
143 last_received_payload_type_ = -1; | 132 last_received_payload_type_ = -1; |
144 last_received_media_payload_type_ = -1; | 133 last_received_media_payload_type_ = -1; |
145 return 0; | 134 return 0; |
146 } | 135 } |
147 | 136 |
148 int32_t RTPPayloadRegistry::RegisterReceivePayload( | |
149 const VideoCodec& video_codec) { | |
150 if (!IsPayloadTypeValid(video_codec.plType)) | |
151 return -1; | |
152 | |
153 rtc::CritScope cs(&crit_sect_); | |
154 | |
155 auto it = payload_type_map_.find(video_codec.plType); | |
156 if (it != payload_type_map_.end()) { | |
157 // We already use this payload type. Check if it's the same as we already | |
158 // have. If same, ignore sending an error. | |
159 if (PayloadIsCompatible(it->second, video_codec)) | |
160 return 0; | |
161 LOG(LS_ERROR) << "Payload type already registered: " | |
162 << static_cast<int>(video_codec.plType); | |
163 return -1; | |
164 } | |
165 | |
166 payload_type_map_[video_codec.plType] = CreatePayloadType(video_codec); | |
167 | |
168 // Successful set of payload type, clear the value of last received payload | |
169 // type since it might mean something else. | |
170 last_received_payload_type_ = -1; | |
171 last_received_media_payload_type_ = -1; | |
172 return 0; | |
173 } | |
174 | |
175 int32_t RTPPayloadRegistry::DeRegisterReceivePayload( | 137 int32_t RTPPayloadRegistry::DeRegisterReceivePayload( |
176 const int8_t payload_type) { | 138 const int8_t payload_type) { |
177 rtc::CritScope cs(&crit_sect_); | 139 rtc::CritScope cs(&crit_sect_); |
178 payload_type_map_.erase(payload_type); | 140 RtpUtility::PayloadTypeMap::iterator it = |
| 141 payload_type_map_.find(payload_type); |
| 142 assert(it != payload_type_map_.end()); |
| 143 delete it->second; |
| 144 payload_type_map_.erase(it); |
179 return 0; | 145 return 0; |
180 } | 146 } |
181 | 147 |
182 // There can't be several codecs with the same rate, frequency and channels | 148 // There can't be several codecs with the same rate, frequency and channels |
183 // for audio codecs, but there can for video. | 149 // for audio codecs, but there can for video. |
184 // Always called from within a critical section. | 150 // Always called from within a critical section. |
185 void RTPPayloadRegistry::DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType( | 151 void RTPPayloadRegistry::DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType( |
186 const CodecInst& audio_codec) { | 152 const char* const payload_name, |
187 for (auto iterator = payload_type_map_.begin(); | 153 const size_t payload_name_length, |
188 iterator != payload_type_map_.end(); ++iterator) { | 154 const uint32_t frequency, |
189 if (PayloadIsCompatible(iterator->second, audio_codec)) { | 155 const size_t channels, |
190 // Remove old setting. | 156 const uint32_t rate) { |
191 payload_type_map_.erase(iterator); | 157 RtpUtility::PayloadTypeMap::iterator iterator = payload_type_map_.begin(); |
192 break; | 158 for (; iterator != payload_type_map_.end(); ++iterator) { |
| 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 } |
193 } | 180 } |
194 } | 181 } |
195 } | 182 } |
196 | 183 |
197 int32_t RTPPayloadRegistry::ReceivePayloadType(const CodecInst& audio_codec, | 184 int32_t RTPPayloadRegistry::ReceivePayloadType(const CodecInst& audio_codec, |
198 int8_t* payload_type) const { | 185 int8_t* payload_type) const { |
199 assert(payload_type); | 186 return ReceivePayloadType(audio_codec.plname, audio_codec.plfreq, |
200 rtc::CritScope cs(&crit_sect_); | 187 audio_codec.channels, std::max(0, audio_codec.rate), |
201 | 188 payload_type); |
202 for (const auto& it : payload_type_map_) { | |
203 if (PayloadIsCompatible(it.second, audio_codec)) { | |
204 *payload_type = it.first; | |
205 return 0; | |
206 } | |
207 } | |
208 return -1; | |
209 } | 189 } |
210 | 190 |
211 int32_t RTPPayloadRegistry::ReceivePayloadType(const VideoCodec& video_codec, | 191 int32_t RTPPayloadRegistry::ReceivePayloadType(const VideoCodec& video_codec, |
212 int8_t* payload_type) const { | 192 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 { |
213 assert(payload_type); | 202 assert(payload_type); |
| 203 size_t payload_name_length = strlen(payload_name); |
| 204 |
214 rtc::CritScope cs(&crit_sect_); | 205 rtc::CritScope cs(&crit_sect_); |
215 | 206 |
216 for (const auto& it : payload_type_map_) { | 207 RtpUtility::PayloadTypeMap::const_iterator it = payload_type_map_.begin(); |
217 if (PayloadIsCompatible(it.second, video_codec)) { | 208 |
218 *payload_type = it.first; | 209 for (; it != payload_type_map_.end(); ++it) { |
219 return 0; | 210 RtpUtility::Payload* payload = it->second; |
| 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) { |
| 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 } |
220 } | 241 } |
221 } | 242 } |
222 return -1; | 243 return -1; |
223 } | 244 } |
224 | 245 |
225 bool RTPPayloadRegistry::RtxEnabled() const { | 246 bool RTPPayloadRegistry::RtxEnabled() const { |
226 rtc::CritScope cs(&crit_sect_); | 247 rtc::CritScope cs(&crit_sect_); |
227 return rtx_; | 248 return rtx_; |
228 } | 249 } |
229 | 250 |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
305 LOG(LS_ERROR) << "Invalid RTX payload type: " << payload_type; | 326 LOG(LS_ERROR) << "Invalid RTX payload type: " << payload_type; |
306 return; | 327 return; |
307 } | 328 } |
308 | 329 |
309 rtx_payload_type_map_[payload_type] = associated_payload_type; | 330 rtx_payload_type_map_[payload_type] = associated_payload_type; |
310 rtx_ = true; | 331 rtx_ = true; |
311 } | 332 } |
312 | 333 |
313 bool RTPPayloadRegistry::IsRed(const RTPHeader& header) const { | 334 bool RTPPayloadRegistry::IsRed(const RTPHeader& header) const { |
314 rtc::CritScope cs(&crit_sect_); | 335 rtc::CritScope cs(&crit_sect_); |
315 auto it = payload_type_map_.find(header.payloadType); | 336 return red_payload_type_ == header.payloadType; |
316 return it != payload_type_map_.end() && _stricmp(it->second.name, "red") == 0; | |
317 } | 337 } |
318 | 338 |
319 bool RTPPayloadRegistry::IsEncapsulated(const RTPHeader& header) const { | 339 bool RTPPayloadRegistry::IsEncapsulated(const RTPHeader& header) const { |
320 return IsRed(header) || IsRtx(header); | 340 return IsRed(header) || IsRtx(header); |
321 } | 341 } |
322 | 342 |
323 bool RTPPayloadRegistry::GetPayloadSpecifics(uint8_t payload_type, | 343 bool RTPPayloadRegistry::GetPayloadSpecifics(uint8_t payload_type, |
324 PayloadUnion* payload) const { | 344 PayloadUnion* payload) const { |
325 rtc::CritScope cs(&crit_sect_); | 345 rtc::CritScope cs(&crit_sect_); |
326 auto it = payload_type_map_.find(payload_type); | 346 RtpUtility::PayloadTypeMap::const_iterator it = |
| 347 payload_type_map_.find(payload_type); |
327 | 348 |
328 // Check that this is a registered payload type. | 349 // Check that this is a registered payload type. |
329 if (it == payload_type_map_.end()) { | 350 if (it == payload_type_map_.end()) { |
330 return false; | 351 return false; |
331 } | 352 } |
332 *payload = it->second.typeSpecific; | 353 *payload = it->second->typeSpecific; |
333 return true; | 354 return true; |
334 } | 355 } |
335 | 356 |
336 int RTPPayloadRegistry::GetPayloadTypeFrequency( | 357 int RTPPayloadRegistry::GetPayloadTypeFrequency( |
337 uint8_t payload_type) const { | 358 uint8_t payload_type) const { |
338 const RtpUtility::Payload* payload = PayloadTypeToPayload(payload_type); | 359 const RtpUtility::Payload* payload = PayloadTypeToPayload(payload_type); |
339 if (!payload) { | 360 if (!payload) { |
340 return -1; | 361 return -1; |
341 } | 362 } |
342 rtc::CritScope cs(&crit_sect_); | 363 rtc::CritScope cs(&crit_sect_); |
343 return payload->audio ? payload->typeSpecific.Audio.frequency | 364 return rtp_payload_strategy_->GetPayloadTypeFrequency(*payload); |
344 : kVideoPayloadTypeFrequency; | |
345 } | 365 } |
346 | 366 |
347 const RtpUtility::Payload* RTPPayloadRegistry::PayloadTypeToPayload( | 367 const RtpUtility::Payload* RTPPayloadRegistry::PayloadTypeToPayload( |
348 uint8_t payload_type) const { | 368 uint8_t payload_type) const { |
349 rtc::CritScope cs(&crit_sect_); | 369 rtc::CritScope cs(&crit_sect_); |
350 | 370 |
351 auto it = payload_type_map_.find(payload_type); | 371 RtpUtility::PayloadTypeMap::const_iterator it = |
| 372 payload_type_map_.find(payload_type); |
352 | 373 |
353 // Check that this is a registered payload type. | 374 // Check that this is a registered payload type. |
354 if (it == payload_type_map_.end()) { | 375 if (it == payload_type_map_.end()) { |
355 return nullptr; | 376 return nullptr; |
356 } | 377 } |
357 | 378 |
358 return &it->second; | 379 return it->second; |
359 } | 380 } |
360 | 381 |
361 void RTPPayloadRegistry::SetIncomingPayloadType(const RTPHeader& header) { | 382 void RTPPayloadRegistry::SetIncomingPayloadType(const RTPHeader& header) { |
362 rtc::CritScope cs(&crit_sect_); | 383 rtc::CritScope cs(&crit_sect_); |
363 if (!IsRtxInternal(header)) | 384 if (!IsRtxInternal(header)) |
364 incoming_payload_type_ = header.payloadType; | 385 incoming_payload_type_ = header.payloadType; |
365 } | 386 } |
366 | 387 |
367 bool RTPPayloadRegistry::ReportMediaPayloadType(uint8_t media_payload_type) { | 388 bool RTPPayloadRegistry::ReportMediaPayloadType(uint8_t media_payload_type) { |
368 rtc::CritScope cs(&crit_sect_); | 389 rtc::CritScope cs(&crit_sect_); |
369 if (last_received_media_payload_type_ == media_payload_type) { | 390 if (last_received_media_payload_type_ == media_payload_type) { |
370 // Media type unchanged. | 391 // Media type unchanged. |
371 return true; | 392 return true; |
372 } | 393 } |
373 last_received_media_payload_type_ = media_payload_type; | 394 last_received_media_payload_type_ = media_payload_type; |
374 return false; | 395 return false; |
375 } | 396 } |
376 | 397 |
377 // Returns -1 if a payload with name |payload_name| is not registered. | 398 class RTPPayloadAudioStrategy : public RTPPayloadStrategy { |
378 int8_t RTPPayloadRegistry::GetPayloadTypeWithName( | 399 public: |
379 const char* payload_name) const { | 400 bool CodecsMustBeUnique() const override { return true; } |
380 rtc::CritScope cs(&crit_sect_); | 401 |
381 for (const auto& it : payload_type_map_) { | 402 bool PayloadIsCompatible(const RtpUtility::Payload& payload, |
382 if (_stricmp(it.second.name, payload_name) == 0) | 403 const uint32_t frequency, |
383 return it.first; | 404 const size_t channels, |
| 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); |
384 } | 412 } |
385 return -1; | 413 |
| 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 } |
386 } | 498 } |
387 | 499 |
388 } // namespace webrtc | 500 } // namespace webrtc |
OLD | NEW |