Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / modules / rtp_rtcp / source / rtp_payload_registry.cc
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
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
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
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
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.
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
180 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
231 void RTPPayloadRegistry::SetRtxStatus(bool enable, uint32_t ssrc) {
232   CriticalSectionScoped cs(crit_sect_.get());
233   rtx_ = enable;
234   ssrc_rtx_ = ssrc;
235 }
236
237 bool RTPPayloadRegistry::RtxEnabled() const {
238   CriticalSectionScoped cs(crit_sect_.get());
239   return rtx_;
240 }
241
242 bool RTPPayloadRegistry::IsRtx(const RTPHeader& header) const {
243   CriticalSectionScoped cs(crit_sect_.get());
244   return IsRtxInternal(header);
245 }
246
247 bool RTPPayloadRegistry::IsRtxInternal(const RTPHeader& header) const {
248   return rtx_ && ssrc_rtx_ == header.ssrc;
249 }
250
251 bool RTPPayloadRegistry::RestoreOriginalPacket(uint8_t** restored_packet,
252                                                const uint8_t* packet,
253                                                int* packet_length,
254                                                uint32_t original_ssrc,
255                                                const RTPHeader& header) const {
256   if (kRtxHeaderSize + header.headerLength > *packet_length) {
257     return false;
258   }
259   const uint8_t* rtx_header = packet + header.headerLength;
260   uint16_t original_sequence_number = (rtx_header[0] << 8) + rtx_header[1];
261
262   // Copy the packet into the restored packet, except for the RTX header.
263   memcpy(*restored_packet, packet, header.headerLength);
264   memcpy(*restored_packet + header.headerLength,
265          packet + header.headerLength + kRtxHeaderSize,
266          *packet_length - header.headerLength - kRtxHeaderSize);
267   *packet_length -= kRtxHeaderSize;
268
269   // Replace the SSRC and the sequence number with the originals.
270   ModuleRTPUtility::AssignUWord16ToBuffer(*restored_packet + 2,
271                                           original_sequence_number);
272   ModuleRTPUtility::AssignUWord32ToBuffer(*restored_packet + 8, original_ssrc);
273
274   CriticalSectionScoped cs(crit_sect_.get());
275
276   if (payload_type_rtx_ != -1) {
277     if (header.payloadType == payload_type_rtx_ &&
278         incoming_payload_type_ != -1) {
279       (*restored_packet)[1] = static_cast<uint8_t>(incoming_payload_type_);
280       if (header.markerBit) {
281         (*restored_packet)[1] |= kRtpMarkerBitMask;  // Marker bit is set.
282       }
283     } else {
284       LOG(LS_WARNING) << "Incorrect RTX configuration, dropping packet.";
285       return false;
286     }
287   }
288   return true;
289 }
290
291 void RTPPayloadRegistry::SetRtxPayloadType(int payload_type) {
292   CriticalSectionScoped cs(crit_sect_.get());
293   payload_type_rtx_ = payload_type;
294 }
295
296 bool RTPPayloadRegistry::IsRed(const RTPHeader& header) const {
297   CriticalSectionScoped cs(crit_sect_.get());
298   return red_payload_type_ == header.payloadType;
299 }
300
301 bool RTPPayloadRegistry::IsEncapsulated(const RTPHeader& header) const {
302   return IsRed(header) || IsRtx(header);
303 }
304
305 bool RTPPayloadRegistry::GetPayloadSpecifics(uint8_t payload_type,
306                                              PayloadUnion* payload) const {
307   CriticalSectionScoped cs(crit_sect_.get());
308   ModuleRTPUtility::PayloadTypeMap::const_iterator it =
309     payload_type_map_.find(payload_type);
310
311   // Check that this is a registered payload type.
312   if (it == payload_type_map_.end()) {
313     return false;
314   }
315   *payload = it->second->typeSpecific;
316   return true;
317 }
318
319 int RTPPayloadRegistry::GetPayloadTypeFrequency(
320     uint8_t payload_type) const {
321   ModuleRTPUtility::Payload* payload;
322   if (!PayloadTypeToPayload(payload_type, payload)) {
323     return -1;
324   }
325   CriticalSectionScoped cs(crit_sect_.get());
326   return rtp_payload_strategy_->GetPayloadTypeFrequency(*payload);
327 }
328
329 bool RTPPayloadRegistry::PayloadTypeToPayload(
330   const uint8_t payload_type,
331   ModuleRTPUtility::Payload*& payload) const {
332   CriticalSectionScoped cs(crit_sect_.get());
333
334   ModuleRTPUtility::PayloadTypeMap::const_iterator it =
335     payload_type_map_.find(payload_type);
336
337   // Check that this is a registered payload type.
338   if (it == payload_type_map_.end()) {
339     return false;
340   }
341
342   payload = it->second;
343   return true;
344 }
345
346 void RTPPayloadRegistry::SetIncomingPayloadType(const RTPHeader& header) {
347   CriticalSectionScoped cs(crit_sect_.get());
348   if (!IsRtxInternal(header))
349     incoming_payload_type_ = header.payloadType;
350 }
351
352 bool RTPPayloadRegistry::ReportMediaPayloadType(uint8_t media_payload_type) {
353   CriticalSectionScoped cs(crit_sect_.get());
354   if (last_received_media_payload_type_ == media_payload_type) {
355     // Media type unchanged.
356     return true;
357   }
358   last_received_media_payload_type_ = media_payload_type;
359   return false;
360 }
361
362 class RTPPayloadAudioStrategy : public RTPPayloadStrategy {
363  public:
364   virtual bool CodecsMustBeUnique() const OVERRIDE { return true; }
365
366   virtual bool PayloadIsCompatible(
367        const ModuleRTPUtility::Payload& payload,
368        const uint32_t frequency,
369        const uint8_t channels,
370        const uint32_t rate) const OVERRIDE {
371     return
372         payload.audio &&
373         payload.typeSpecific.Audio.frequency == frequency &&
374         payload.typeSpecific.Audio.channels == channels &&
375         (payload.typeSpecific.Audio.rate == rate ||
376             payload.typeSpecific.Audio.rate == 0 || rate == 0);
377   }
378
379   virtual void UpdatePayloadRate(
380       ModuleRTPUtility::Payload* payload,
381       const uint32_t rate) const OVERRIDE {
382     payload->typeSpecific.Audio.rate = rate;
383   }
384
385   virtual ModuleRTPUtility::Payload* CreatePayloadType(
386       const char payloadName[RTP_PAYLOAD_NAME_SIZE],
387       const int8_t payloadType,
388       const uint32_t frequency,
389       const uint8_t channels,
390       const uint32_t rate) const OVERRIDE {
391     ModuleRTPUtility::Payload* payload = new ModuleRTPUtility::Payload;
392     payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
393     strncpy(payload->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1);
394     assert(frequency >= 1000);
395     payload->typeSpecific.Audio.frequency = frequency;
396     payload->typeSpecific.Audio.channels = channels;
397     payload->typeSpecific.Audio.rate = rate;
398     payload->audio = true;
399     return payload;
400   }
401
402   int GetPayloadTypeFrequency(
403       const ModuleRTPUtility::Payload& payload) const {
404     return payload.typeSpecific.Audio.frequency;
405   }
406 };
407
408 class RTPPayloadVideoStrategy : public RTPPayloadStrategy {
409  public:
410   virtual bool CodecsMustBeUnique() const OVERRIDE { return false; }
411
412   virtual bool PayloadIsCompatible(
413       const ModuleRTPUtility::Payload& payload,
414       const uint32_t frequency,
415       const uint8_t channels,
416       const uint32_t rate) const OVERRIDE {
417     return !payload.audio;
418   }
419
420   virtual void UpdatePayloadRate(
421       ModuleRTPUtility::Payload* payload,
422       const uint32_t rate) const OVERRIDE {
423     payload->typeSpecific.Video.maxRate = rate;
424   }
425
426   virtual ModuleRTPUtility::Payload* CreatePayloadType(
427       const char payloadName[RTP_PAYLOAD_NAME_SIZE],
428       const int8_t payloadType,
429       const uint32_t frequency,
430       const uint8_t channels,
431       const uint32_t rate) const OVERRIDE {
432     RtpVideoCodecTypes videoType = kRtpVideoGeneric;
433     if (ModuleRTPUtility::StringCompare(payloadName, "VP8", 3)) {
434       videoType = kRtpVideoVp8;
435     } else if (ModuleRTPUtility::StringCompare(payloadName, "I420", 4)) {
436       videoType = kRtpVideoGeneric;
437     } else if (ModuleRTPUtility::StringCompare(payloadName, "ULPFEC", 6)) {
438       videoType = kRtpVideoNone;
439     } else {
440       videoType = kRtpVideoGeneric;
441     }
442     ModuleRTPUtility::Payload* payload = new ModuleRTPUtility::Payload;
443
444     payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
445     strncpy(payload->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1);
446     payload->typeSpecific.Video.videoCodecType = videoType;
447     payload->typeSpecific.Video.maxRate = rate;
448     payload->audio = false;
449     return payload;
450   }
451
452   int GetPayloadTypeFrequency(
453       const ModuleRTPUtility::Payload& payload) const {
454     return kVideoPayloadTypeFrequency;
455   }
456 };
457
458 RTPPayloadStrategy* RTPPayloadStrategy::CreateStrategy(
459     const bool handling_audio) {
460   if (handling_audio) {
461     return new RTPPayloadAudioStrategy();
462   } else {
463     return new RTPPayloadVideoStrategy();
464   }
465 }
466
467 }  // namespace webrtc