• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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