1 /*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h"
12
13 #include "webrtc/system_wrappers/interface/logging.h"
14
15 namespace webrtc {
16
RTPPayloadRegistry(RTPPayloadStrategy * rtp_payload_strategy)17 RTPPayloadRegistry::RTPPayloadRegistry(
18 RTPPayloadStrategy* rtp_payload_strategy)
19 : crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
20 rtp_payload_strategy_(rtp_payload_strategy),
21 red_payload_type_(-1),
22 ulpfec_payload_type_(-1),
23 incoming_payload_type_(-1),
24 last_received_payload_type_(-1),
25 last_received_media_payload_type_(-1),
26 rtx_(false),
27 payload_type_rtx_(-1),
28 ssrc_rtx_(0) {}
29
~RTPPayloadRegistry()30 RTPPayloadRegistry::~RTPPayloadRegistry() {
31 while (!payload_type_map_.empty()) {
32 ModuleRTPUtility::PayloadTypeMap::iterator it = payload_type_map_.begin();
33 delete it->second;
34 payload_type_map_.erase(it);
35 }
36 }
37
RegisterReceivePayload(const char payload_name[RTP_PAYLOAD_NAME_SIZE],const int8_t payload_type,const uint32_t frequency,const uint8_t channels,const uint32_t rate,bool * created_new_payload)38 int32_t RTPPayloadRegistry::RegisterReceivePayload(
39 const char payload_name[RTP_PAYLOAD_NAME_SIZE],
40 const int8_t payload_type,
41 const uint32_t frequency,
42 const uint8_t channels,
43 const uint32_t rate,
44 bool* created_new_payload) {
45 assert(payload_type >= 0);
46 assert(payload_name);
47 *created_new_payload = false;
48
49 // Sanity check.
50 switch (payload_type) {
51 // Reserved payload types to avoid RTCP conflicts when marker bit is set.
52 case 64: // 192 Full INTRA-frame request.
53 case 72: // 200 Sender report.
54 case 73: // 201 Receiver report.
55 case 74: // 202 Source description.
56 case 75: // 203 Goodbye.
57 case 76: // 204 Application-defined.
58 case 77: // 205 Transport layer FB message.
59 case 78: // 206 Payload-specific FB message.
60 case 79: // 207 Extended report.
61 LOG(LS_ERROR) << "Can't register invalid receiver payload type: "
62 << payload_type;
63 return -1;
64 default:
65 break;
66 }
67
68 size_t payload_name_length = strlen(payload_name);
69
70 CriticalSectionScoped cs(crit_sect_.get());
71
72 ModuleRTPUtility::PayloadTypeMap::iterator it =
73 payload_type_map_.find(payload_type);
74
75 if (it != payload_type_map_.end()) {
76 // We already use this payload type.
77 ModuleRTPUtility::Payload* payload = it->second;
78
79 assert(payload);
80
81 size_t name_length = strlen(payload->name);
82
83 // Check if it's the same as we already have.
84 // If same, ignore sending an error.
85 if (payload_name_length == name_length &&
86 ModuleRTPUtility::StringCompare(
87 payload->name, payload_name, payload_name_length)) {
88 if (rtp_payload_strategy_->PayloadIsCompatible(*payload, frequency,
89 channels, rate)) {
90 rtp_payload_strategy_->UpdatePayloadRate(payload, rate);
91 return 0;
92 }
93 }
94 LOG(LS_ERROR) << "Payload type already registered: " << payload_type;
95 return -1;
96 }
97
98 if (rtp_payload_strategy_->CodecsMustBeUnique()) {
99 DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType(
100 payload_name, payload_name_length, frequency, channels, rate);
101 }
102
103 ModuleRTPUtility::Payload* payload = NULL;
104
105 // Save the RED payload type. Used in both audio and video.
106 if (ModuleRTPUtility::StringCompare(payload_name, "red", 3)) {
107 red_payload_type_ = payload_type;
108 payload = new ModuleRTPUtility::Payload;
109 memset(payload, 0, sizeof(*payload));
110 payload->audio = false;
111 strncpy(payload->name, payload_name, RTP_PAYLOAD_NAME_SIZE - 1);
112 } else if (ModuleRTPUtility::StringCompare(payload_name, "ulpfec", 3)) {
113 ulpfec_payload_type_ = payload_type;
114 payload = new ModuleRTPUtility::Payload;
115 memset(payload, 0, sizeof(*payload));
116 payload->audio = false;
117 strncpy(payload->name, payload_name, RTP_PAYLOAD_NAME_SIZE - 1);
118 } else {
119 *created_new_payload = true;
120 payload = rtp_payload_strategy_->CreatePayloadType(
121 payload_name, payload_type, frequency, channels, rate);
122 }
123 payload_type_map_[payload_type] = payload;
124
125 // Successful set of payload type, clear the value of last received payload
126 // type since it might mean something else.
127 last_received_payload_type_ = -1;
128 last_received_media_payload_type_ = -1;
129 return 0;
130 }
131
DeRegisterReceivePayload(const int8_t payload_type)132 int32_t RTPPayloadRegistry::DeRegisterReceivePayload(
133 const int8_t payload_type) {
134 CriticalSectionScoped cs(crit_sect_.get());
135 ModuleRTPUtility::PayloadTypeMap::iterator it =
136 payload_type_map_.find(payload_type);
137 assert(it != payload_type_map_.end());
138 delete it->second;
139 payload_type_map_.erase(it);
140 return 0;
141 }
142
143 // There can't be several codecs with the same rate, frequency and channels
144 // for audio codecs, but there can for video.
145 // Always called from within a critical section.
DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType(const char payload_name[RTP_PAYLOAD_NAME_SIZE],const size_t payload_name_length,const uint32_t frequency,const uint8_t channels,const uint32_t rate)146 void RTPPayloadRegistry::DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType(
147 const char payload_name[RTP_PAYLOAD_NAME_SIZE],
148 const size_t payload_name_length,
149 const uint32_t frequency,
150 const uint8_t channels,
151 const uint32_t rate) {
152 ModuleRTPUtility::PayloadTypeMap::iterator iterator =
153 payload_type_map_.begin();
154 for (; iterator != payload_type_map_.end(); ++iterator) {
155 ModuleRTPUtility::Payload* payload = iterator->second;
156 size_t name_length = strlen(payload->name);
157
158 if (payload_name_length == name_length
159 && ModuleRTPUtility::StringCompare(payload->name, payload_name,
160 payload_name_length)) {
161 // We found the payload name in the list.
162 // If audio, check frequency and rate.
163 if (payload->audio) {
164 if (rtp_payload_strategy_->PayloadIsCompatible(*payload, frequency,
165 channels, rate)) {
166 // Remove old setting.
167 delete payload;
168 payload_type_map_.erase(iterator);
169 break;
170 }
171 } else if (ModuleRTPUtility::StringCompare(payload_name, "red", 3)) {
172 delete payload;
173 payload_type_map_.erase(iterator);
174 break;
175 }
176 }
177 }
178 }
179
ReceivePayloadType(const char payload_name[RTP_PAYLOAD_NAME_SIZE],const uint32_t frequency,const uint8_t channels,const uint32_t rate,int8_t * payload_type) const180 int32_t RTPPayloadRegistry::ReceivePayloadType(
181 const char payload_name[RTP_PAYLOAD_NAME_SIZE],
182 const uint32_t frequency,
183 const uint8_t channels,
184 const uint32_t rate,
185 int8_t* payload_type) const {
186 assert(payload_type);
187 size_t payload_name_length = strlen(payload_name);
188
189 CriticalSectionScoped cs(crit_sect_.get());
190
191 ModuleRTPUtility::PayloadTypeMap::const_iterator it =
192 payload_type_map_.begin();
193
194 for (; it != payload_type_map_.end(); ++it) {
195 ModuleRTPUtility::Payload* payload = it->second;
196 assert(payload);
197
198 size_t name_length = strlen(payload->name);
199 if (payload_name_length == name_length &&
200 ModuleRTPUtility::StringCompare(
201 payload->name, payload_name, payload_name_length)) {
202 // Name matches.
203 if (payload->audio) {
204 if (rate == 0) {
205 // [default] audio, check freq and channels.
206 if (payload->typeSpecific.Audio.frequency == frequency &&
207 payload->typeSpecific.Audio.channels == channels) {
208 *payload_type = it->first;
209 return 0;
210 }
211 } else {
212 // Non-default audio, check freq, channels and rate.
213 if (payload->typeSpecific.Audio.frequency == frequency &&
214 payload->typeSpecific.Audio.channels == channels &&
215 payload->typeSpecific.Audio.rate == rate) {
216 // extra rate condition added
217 *payload_type = it->first;
218 return 0;
219 }
220 }
221 } else {
222 // Video.
223 *payload_type = it->first;
224 return 0;
225 }
226 }
227 }
228 return -1;
229 }
230
RtxEnabled() const231 bool RTPPayloadRegistry::RtxEnabled() const {
232 CriticalSectionScoped cs(crit_sect_.get());
233 return rtx_;
234 }
235
IsRtx(const RTPHeader & header) const236 bool RTPPayloadRegistry::IsRtx(const RTPHeader& header) const {
237 CriticalSectionScoped cs(crit_sect_.get());
238 return IsRtxInternal(header);
239 }
240
IsRtxInternal(const RTPHeader & header) const241 bool RTPPayloadRegistry::IsRtxInternal(const RTPHeader& header) const {
242 return rtx_ && ssrc_rtx_ == header.ssrc;
243 }
244
RestoreOriginalPacket(uint8_t ** restored_packet,const uint8_t * packet,int * packet_length,uint32_t original_ssrc,const RTPHeader & header) const245 bool RTPPayloadRegistry::RestoreOriginalPacket(uint8_t** restored_packet,
246 const uint8_t* packet,
247 int* packet_length,
248 uint32_t original_ssrc,
249 const RTPHeader& header) const {
250 if (kRtxHeaderSize + header.headerLength > *packet_length) {
251 return false;
252 }
253 const uint8_t* rtx_header = packet + header.headerLength;
254 uint16_t original_sequence_number = (rtx_header[0] << 8) + rtx_header[1];
255
256 // Copy the packet into the restored packet, except for the RTX header.
257 memcpy(*restored_packet, packet, header.headerLength);
258 memcpy(*restored_packet + header.headerLength,
259 packet + header.headerLength + kRtxHeaderSize,
260 *packet_length - header.headerLength - kRtxHeaderSize);
261 *packet_length -= kRtxHeaderSize;
262
263 // Replace the SSRC and the sequence number with the originals.
264 ModuleRTPUtility::AssignUWord16ToBuffer(*restored_packet + 2,
265 original_sequence_number);
266 ModuleRTPUtility::AssignUWord32ToBuffer(*restored_packet + 8, original_ssrc);
267
268 CriticalSectionScoped cs(crit_sect_.get());
269
270 if (payload_type_rtx_ != -1) {
271 if (header.payloadType == payload_type_rtx_ &&
272 incoming_payload_type_ != -1) {
273 (*restored_packet)[1] = static_cast<uint8_t>(incoming_payload_type_);
274 if (header.markerBit) {
275 (*restored_packet)[1] |= kRtpMarkerBitMask; // Marker bit is set.
276 }
277 } else {
278 LOG(LS_WARNING) << "Incorrect RTX configuration, dropping packet.";
279 return false;
280 }
281 }
282 return true;
283 }
284
SetRtxSsrc(uint32_t ssrc)285 void RTPPayloadRegistry::SetRtxSsrc(uint32_t ssrc) {
286 CriticalSectionScoped cs(crit_sect_.get());
287 ssrc_rtx_ = ssrc;
288 rtx_ = true;
289 }
290
SetRtxPayloadType(int payload_type)291 void RTPPayloadRegistry::SetRtxPayloadType(int payload_type) {
292 CriticalSectionScoped cs(crit_sect_.get());
293 assert(payload_type >= 0);
294 payload_type_rtx_ = payload_type;
295 rtx_ = true;
296 }
297
IsRed(const RTPHeader & header) const298 bool RTPPayloadRegistry::IsRed(const RTPHeader& header) const {
299 CriticalSectionScoped cs(crit_sect_.get());
300 return red_payload_type_ == header.payloadType;
301 }
302
IsEncapsulated(const RTPHeader & header) const303 bool RTPPayloadRegistry::IsEncapsulated(const RTPHeader& header) const {
304 return IsRed(header) || IsRtx(header);
305 }
306
GetPayloadSpecifics(uint8_t payload_type,PayloadUnion * payload) const307 bool RTPPayloadRegistry::GetPayloadSpecifics(uint8_t payload_type,
308 PayloadUnion* payload) const {
309 CriticalSectionScoped cs(crit_sect_.get());
310 ModuleRTPUtility::PayloadTypeMap::const_iterator it =
311 payload_type_map_.find(payload_type);
312
313 // Check that this is a registered payload type.
314 if (it == payload_type_map_.end()) {
315 return false;
316 }
317 *payload = it->second->typeSpecific;
318 return true;
319 }
320
GetPayloadTypeFrequency(uint8_t payload_type) const321 int RTPPayloadRegistry::GetPayloadTypeFrequency(
322 uint8_t payload_type) const {
323 ModuleRTPUtility::Payload* payload;
324 if (!PayloadTypeToPayload(payload_type, payload)) {
325 return -1;
326 }
327 CriticalSectionScoped cs(crit_sect_.get());
328 return rtp_payload_strategy_->GetPayloadTypeFrequency(*payload);
329 }
330
PayloadTypeToPayload(const uint8_t payload_type,ModuleRTPUtility::Payload * & payload) const331 bool RTPPayloadRegistry::PayloadTypeToPayload(
332 const uint8_t payload_type,
333 ModuleRTPUtility::Payload*& payload) const {
334 CriticalSectionScoped cs(crit_sect_.get());
335
336 ModuleRTPUtility::PayloadTypeMap::const_iterator it =
337 payload_type_map_.find(payload_type);
338
339 // Check that this is a registered payload type.
340 if (it == payload_type_map_.end()) {
341 return false;
342 }
343
344 payload = it->second;
345 return true;
346 }
347
SetIncomingPayloadType(const RTPHeader & header)348 void RTPPayloadRegistry::SetIncomingPayloadType(const RTPHeader& header) {
349 CriticalSectionScoped cs(crit_sect_.get());
350 if (!IsRtxInternal(header))
351 incoming_payload_type_ = header.payloadType;
352 }
353
ReportMediaPayloadType(uint8_t media_payload_type)354 bool RTPPayloadRegistry::ReportMediaPayloadType(uint8_t media_payload_type) {
355 CriticalSectionScoped cs(crit_sect_.get());
356 if (last_received_media_payload_type_ == media_payload_type) {
357 // Media type unchanged.
358 return true;
359 }
360 last_received_media_payload_type_ = media_payload_type;
361 return false;
362 }
363
364 class RTPPayloadAudioStrategy : public RTPPayloadStrategy {
365 public:
CodecsMustBeUnique() const366 virtual bool CodecsMustBeUnique() const OVERRIDE { return true; }
367
PayloadIsCompatible(const ModuleRTPUtility::Payload & payload,const uint32_t frequency,const uint8_t channels,const uint32_t rate) const368 virtual bool PayloadIsCompatible(
369 const ModuleRTPUtility::Payload& payload,
370 const uint32_t frequency,
371 const uint8_t channels,
372 const uint32_t rate) const OVERRIDE {
373 return
374 payload.audio &&
375 payload.typeSpecific.Audio.frequency == frequency &&
376 payload.typeSpecific.Audio.channels == channels &&
377 (payload.typeSpecific.Audio.rate == rate ||
378 payload.typeSpecific.Audio.rate == 0 || rate == 0);
379 }
380
UpdatePayloadRate(ModuleRTPUtility::Payload * payload,const uint32_t rate) const381 virtual void UpdatePayloadRate(
382 ModuleRTPUtility::Payload* payload,
383 const uint32_t rate) const OVERRIDE {
384 payload->typeSpecific.Audio.rate = rate;
385 }
386
CreatePayloadType(const char payloadName[RTP_PAYLOAD_NAME_SIZE],const int8_t payloadType,const uint32_t frequency,const uint8_t channels,const uint32_t rate) const387 virtual ModuleRTPUtility::Payload* CreatePayloadType(
388 const char payloadName[RTP_PAYLOAD_NAME_SIZE],
389 const int8_t payloadType,
390 const uint32_t frequency,
391 const uint8_t channels,
392 const uint32_t rate) const OVERRIDE {
393 ModuleRTPUtility::Payload* payload = new ModuleRTPUtility::Payload;
394 payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
395 strncpy(payload->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1);
396 assert(frequency >= 1000);
397 payload->typeSpecific.Audio.frequency = frequency;
398 payload->typeSpecific.Audio.channels = channels;
399 payload->typeSpecific.Audio.rate = rate;
400 payload->audio = true;
401 return payload;
402 }
403
GetPayloadTypeFrequency(const ModuleRTPUtility::Payload & payload) const404 int GetPayloadTypeFrequency(
405 const ModuleRTPUtility::Payload& payload) const {
406 return payload.typeSpecific.Audio.frequency;
407 }
408 };
409
410 class RTPPayloadVideoStrategy : public RTPPayloadStrategy {
411 public:
CodecsMustBeUnique() const412 virtual bool CodecsMustBeUnique() const OVERRIDE { return false; }
413
PayloadIsCompatible(const ModuleRTPUtility::Payload & payload,const uint32_t frequency,const uint8_t channels,const uint32_t rate) const414 virtual bool PayloadIsCompatible(
415 const ModuleRTPUtility::Payload& payload,
416 const uint32_t frequency,
417 const uint8_t channels,
418 const uint32_t rate) const OVERRIDE {
419 return !payload.audio;
420 }
421
UpdatePayloadRate(ModuleRTPUtility::Payload * payload,const uint32_t rate) const422 virtual void UpdatePayloadRate(
423 ModuleRTPUtility::Payload* payload,
424 const uint32_t rate) const OVERRIDE {
425 payload->typeSpecific.Video.maxRate = rate;
426 }
427
CreatePayloadType(const char payloadName[RTP_PAYLOAD_NAME_SIZE],const int8_t payloadType,const uint32_t frequency,const uint8_t channels,const uint32_t rate) const428 virtual ModuleRTPUtility::Payload* CreatePayloadType(
429 const char payloadName[RTP_PAYLOAD_NAME_SIZE],
430 const int8_t payloadType,
431 const uint32_t frequency,
432 const uint8_t channels,
433 const uint32_t rate) const OVERRIDE {
434 RtpVideoCodecTypes videoType = kRtpVideoGeneric;
435 if (ModuleRTPUtility::StringCompare(payloadName, "VP8", 3)) {
436 videoType = kRtpVideoVp8;
437 } else if (ModuleRTPUtility::StringCompare(payloadName, "I420", 4)) {
438 videoType = kRtpVideoGeneric;
439 } else if (ModuleRTPUtility::StringCompare(payloadName, "ULPFEC", 6)) {
440 videoType = kRtpVideoNone;
441 } else {
442 videoType = kRtpVideoGeneric;
443 }
444 ModuleRTPUtility::Payload* payload = new ModuleRTPUtility::Payload;
445
446 payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
447 strncpy(payload->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1);
448 payload->typeSpecific.Video.videoCodecType = videoType;
449 payload->typeSpecific.Video.maxRate = rate;
450 payload->audio = false;
451 return payload;
452 }
453
GetPayloadTypeFrequency(const ModuleRTPUtility::Payload & payload) const454 int GetPayloadTypeFrequency(
455 const ModuleRTPUtility::Payload& payload) const {
456 return kVideoPayloadTypeFrequency;
457 }
458 };
459
CreateStrategy(const bool handling_audio)460 RTPPayloadStrategy* RTPPayloadStrategy::CreateStrategy(
461 const bool handling_audio) {
462 if (handling_audio) {
463 return new RTPPayloadAudioStrategy();
464 } else {
465 return new RTPPayloadVideoStrategy();
466 }
467 }
468
469 } // namespace webrtc
470