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