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/include/rtp_payload_registry.h"
12
13#include "webrtc/base/logging.h"
14#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
15
16namespace webrtc {
17
18RTPPayloadRegistry::RTPPayloadRegistry(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      rtx_payload_type_(-1),
28      use_rtx_payload_mapping_on_restore_(false),
29      ssrc_rtx_(0) {}
30
31RTPPayloadRegistry::~RTPPayloadRegistry() {
32  while (!payload_type_map_.empty()) {
33    RtpUtility::PayloadTypeMap::iterator it = payload_type_map_.begin();
34    delete it->second;
35    payload_type_map_.erase(it);
36  }
37}
38
39int32_t RTPPayloadRegistry::RegisterReceivePayload(
40    const char payload_name[RTP_PAYLOAD_NAME_SIZE],
41    const int8_t payload_type,
42    const uint32_t frequency,
43    const size_t channels,
44    const uint32_t rate,
45    bool* created_new_payload) {
46  assert(payload_type >= 0);
47  assert(payload_name);
48  *created_new_payload = false;
49
50  // Sanity check.
51  switch (payload_type) {
52    // Reserved payload types to avoid RTCP conflicts when marker bit is set.
53    case 64:        //  192 Full INTRA-frame request.
54    case 72:        //  200 Sender report.
55    case 73:        //  201 Receiver report.
56    case 74:        //  202 Source description.
57    case 75:        //  203 Goodbye.
58    case 76:        //  204 Application-defined.
59    case 77:        //  205 Transport layer FB message.
60    case 78:        //  206 Payload-specific FB message.
61    case 79:        //  207 Extended report.
62      LOG(LS_ERROR) << "Can't register invalid receiver payload type: "
63                    << payload_type;
64      return -1;
65    default:
66      break;
67  }
68
69  size_t payload_name_length = strlen(payload_name);
70
71  CriticalSectionScoped cs(crit_sect_.get());
72
73  RtpUtility::PayloadTypeMap::iterator it =
74      payload_type_map_.find(payload_type);
75
76  if (it != payload_type_map_.end()) {
77    // We already use this payload type.
78    RtpUtility::Payload* payload = it->second;
79
80    assert(payload);
81
82    size_t name_length = strlen(payload->name);
83
84    // Check if it's the same as we already have.
85    // If same, ignore sending an error.
86    if (payload_name_length == name_length &&
87        RtpUtility::StringCompare(
88            payload->name, payload_name, payload_name_length)) {
89      if (rtp_payload_strategy_->PayloadIsCompatible(*payload, frequency,
90                                                     channels, rate)) {
91        rtp_payload_strategy_->UpdatePayloadRate(payload, rate);
92        return 0;
93      }
94    }
95    LOG(LS_ERROR) << "Payload type already registered: "
96                  << static_cast<int>(payload_type);
97    return -1;
98  }
99
100  if (rtp_payload_strategy_->CodecsMustBeUnique()) {
101    DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType(
102        payload_name, payload_name_length, frequency, channels, rate);
103  }
104
105  RtpUtility::Payload* payload = rtp_payload_strategy_->CreatePayloadType(
106      payload_name, payload_type, frequency, channels, rate);
107
108  payload_type_map_[payload_type] = payload;
109  *created_new_payload = true;
110
111  if (RtpUtility::StringCompare(payload_name, "red", 3)) {
112    red_payload_type_ = payload_type;
113  } else if (RtpUtility::StringCompare(payload_name, "ulpfec", 6)) {
114    ulpfec_payload_type_ = payload_type;
115  }
116
117  // Successful set of payload type, clear the value of last received payload
118  // type since it might mean something else.
119  last_received_payload_type_ = -1;
120  last_received_media_payload_type_ = -1;
121  return 0;
122}
123
124int32_t RTPPayloadRegistry::DeRegisterReceivePayload(
125    const int8_t payload_type) {
126  CriticalSectionScoped cs(crit_sect_.get());
127  RtpUtility::PayloadTypeMap::iterator it =
128      payload_type_map_.find(payload_type);
129  assert(it != payload_type_map_.end());
130  delete it->second;
131  payload_type_map_.erase(it);
132  return 0;
133}
134
135// There can't be several codecs with the same rate, frequency and channels
136// for audio codecs, but there can for video.
137// Always called from within a critical section.
138void RTPPayloadRegistry::DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType(
139    const char payload_name[RTP_PAYLOAD_NAME_SIZE],
140    const size_t payload_name_length,
141    const uint32_t frequency,
142    const size_t channels,
143    const uint32_t rate) {
144  RtpUtility::PayloadTypeMap::iterator iterator = payload_type_map_.begin();
145  for (; iterator != payload_type_map_.end(); ++iterator) {
146    RtpUtility::Payload* payload = iterator->second;
147    size_t name_length = strlen(payload->name);
148
149    if (payload_name_length == name_length &&
150        RtpUtility::StringCompare(
151            payload->name, payload_name, payload_name_length)) {
152      // We found the payload name in the list.
153      // If audio, check frequency and rate.
154      if (payload->audio) {
155        if (rtp_payload_strategy_->PayloadIsCompatible(*payload, frequency,
156                                                       channels, rate)) {
157          // Remove old setting.
158          delete payload;
159          payload_type_map_.erase(iterator);
160          break;
161        }
162      } else if (RtpUtility::StringCompare(payload_name, "red", 3)) {
163        delete payload;
164        payload_type_map_.erase(iterator);
165        break;
166      }
167    }
168  }
169}
170
171int32_t RTPPayloadRegistry::ReceivePayloadType(
172    const char payload_name[RTP_PAYLOAD_NAME_SIZE],
173    const uint32_t frequency,
174    const size_t channels,
175    const uint32_t rate,
176    int8_t* payload_type) const {
177  assert(payload_type);
178  size_t payload_name_length = strlen(payload_name);
179
180  CriticalSectionScoped cs(crit_sect_.get());
181
182  RtpUtility::PayloadTypeMap::const_iterator it = payload_type_map_.begin();
183
184  for (; it != payload_type_map_.end(); ++it) {
185    RtpUtility::Payload* payload = it->second;
186    assert(payload);
187
188    size_t name_length = strlen(payload->name);
189    if (payload_name_length == name_length &&
190        RtpUtility::StringCompare(
191            payload->name, payload_name, payload_name_length)) {
192      // Name matches.
193      if (payload->audio) {
194        if (rate == 0) {
195          // [default] audio, check freq and channels.
196          if (payload->typeSpecific.Audio.frequency == frequency &&
197              payload->typeSpecific.Audio.channels == channels) {
198            *payload_type = it->first;
199            return 0;
200          }
201        } else {
202          // Non-default audio, check freq, channels and rate.
203          if (payload->typeSpecific.Audio.frequency == frequency &&
204              payload->typeSpecific.Audio.channels == channels &&
205              payload->typeSpecific.Audio.rate == rate) {
206            // extra rate condition added
207            *payload_type = it->first;
208            return 0;
209          }
210        }
211      } else {
212        // Video.
213        *payload_type = it->first;
214        return 0;
215      }
216    }
217  }
218  return -1;
219}
220
221bool RTPPayloadRegistry::RtxEnabled() const {
222  CriticalSectionScoped cs(crit_sect_.get());
223  return rtx_;
224}
225
226bool RTPPayloadRegistry::IsRtx(const RTPHeader& header) const {
227  CriticalSectionScoped cs(crit_sect_.get());
228  return IsRtxInternal(header);
229}
230
231bool RTPPayloadRegistry::IsRtxInternal(const RTPHeader& header) const {
232  return rtx_ && ssrc_rtx_ == header.ssrc;
233}
234
235bool RTPPayloadRegistry::RestoreOriginalPacket(uint8_t** restored_packet,
236                                               const uint8_t* packet,
237                                               size_t* packet_length,
238                                               uint32_t original_ssrc,
239                                               const RTPHeader& header) const {
240  return RestoreOriginalPacket(*restored_packet, packet, packet_length,
241                               original_ssrc, header);
242}
243
244bool RTPPayloadRegistry::RestoreOriginalPacket(uint8_t* restored_packet,
245                                               const uint8_t* packet,
246                                               size_t* packet_length,
247                                               uint32_t original_ssrc,
248                                               const RTPHeader& header) const {
249  if (kRtxHeaderSize + header.headerLength + header.paddingLength >
250      *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  ByteWriter<uint16_t>::WriteBigEndian(restored_packet + 2,
265                                       original_sequence_number);
266  ByteWriter<uint32_t>::WriteBigEndian(restored_packet + 8, original_ssrc);
267
268  CriticalSectionScoped cs(crit_sect_.get());
269  if (!rtx_)
270    return true;
271
272  int associated_payload_type;
273  auto apt_mapping = rtx_payload_type_map_.find(header.payloadType);
274  if (use_rtx_payload_mapping_on_restore_ &&
275      apt_mapping != rtx_payload_type_map_.end()) {
276    associated_payload_type = apt_mapping->second;
277  } else {
278    // In the future, this will be a bug. For now, just assume this RTX packet
279    // matches the last non-RTX payload type we received. There are cases where
280    // this could break, especially where RTX is sent outside of NACKing (e.g.
281    // padding with redundant payloads).
282    if (rtx_payload_type_ == -1 || incoming_payload_type_ == -1) {
283      LOG(LS_WARNING) << "Incorrect RTX configuration, dropping packet.";
284      return false;
285    }
286    associated_payload_type = incoming_payload_type_;
287  }
288
289  restored_packet[1] = static_cast<uint8_t>(associated_payload_type);
290  if (header.markerBit) {
291    restored_packet[1] |= kRtpMarkerBitMask;  // Marker bit is set.
292  }
293  return true;
294}
295
296void RTPPayloadRegistry::SetRtxSsrc(uint32_t ssrc) {
297  CriticalSectionScoped cs(crit_sect_.get());
298  ssrc_rtx_ = ssrc;
299  rtx_ = true;
300}
301
302bool RTPPayloadRegistry::GetRtxSsrc(uint32_t* ssrc) const {
303  CriticalSectionScoped cs(crit_sect_.get());
304  *ssrc = ssrc_rtx_;
305  return rtx_;
306}
307
308void RTPPayloadRegistry::SetRtxPayloadType(int payload_type,
309                                           int associated_payload_type) {
310  CriticalSectionScoped cs(crit_sect_.get());
311  if (payload_type < 0) {
312    LOG(LS_ERROR) << "Invalid RTX payload type: " << payload_type;
313    return;
314  }
315
316  rtx_payload_type_map_[payload_type] = associated_payload_type;
317  rtx_ = true;
318  rtx_payload_type_ = payload_type;
319}
320
321bool RTPPayloadRegistry::IsRed(const RTPHeader& header) const {
322  CriticalSectionScoped cs(crit_sect_.get());
323  return red_payload_type_ == header.payloadType;
324}
325
326bool RTPPayloadRegistry::IsEncapsulated(const RTPHeader& header) const {
327  return IsRed(header) || IsRtx(header);
328}
329
330bool RTPPayloadRegistry::GetPayloadSpecifics(uint8_t payload_type,
331                                             PayloadUnion* payload) const {
332  CriticalSectionScoped cs(crit_sect_.get());
333  RtpUtility::PayloadTypeMap::const_iterator it =
334      payload_type_map_.find(payload_type);
335
336  // Check that this is a registered payload type.
337  if (it == payload_type_map_.end()) {
338    return false;
339  }
340  *payload = it->second->typeSpecific;
341  return true;
342}
343
344int RTPPayloadRegistry::GetPayloadTypeFrequency(
345    uint8_t payload_type) const {
346  const RtpUtility::Payload* payload = PayloadTypeToPayload(payload_type);
347  if (!payload) {
348    return -1;
349  }
350  CriticalSectionScoped cs(crit_sect_.get());
351  return rtp_payload_strategy_->GetPayloadTypeFrequency(*payload);
352}
353
354const RtpUtility::Payload* RTPPayloadRegistry::PayloadTypeToPayload(
355    uint8_t payload_type) const {
356  CriticalSectionScoped cs(crit_sect_.get());
357
358  RtpUtility::PayloadTypeMap::const_iterator it =
359      payload_type_map_.find(payload_type);
360
361  // Check that this is a registered payload type.
362  if (it == payload_type_map_.end()) {
363    return nullptr;
364  }
365
366  return it->second;
367}
368
369void RTPPayloadRegistry::SetIncomingPayloadType(const RTPHeader& header) {
370  CriticalSectionScoped cs(crit_sect_.get());
371  if (!IsRtxInternal(header))
372    incoming_payload_type_ = header.payloadType;
373}
374
375bool RTPPayloadRegistry::ReportMediaPayloadType(uint8_t media_payload_type) {
376  CriticalSectionScoped cs(crit_sect_.get());
377  if (last_received_media_payload_type_ == media_payload_type) {
378    // Media type unchanged.
379    return true;
380  }
381  last_received_media_payload_type_ = media_payload_type;
382  return false;
383}
384
385class RTPPayloadAudioStrategy : public RTPPayloadStrategy {
386 public:
387  bool CodecsMustBeUnique() const override { return true; }
388
389  bool PayloadIsCompatible(const RtpUtility::Payload& payload,
390                           const uint32_t frequency,
391                           const size_t channels,
392                           const uint32_t rate) const override {
393    return
394        payload.audio &&
395        payload.typeSpecific.Audio.frequency == frequency &&
396        payload.typeSpecific.Audio.channels == channels &&
397        (payload.typeSpecific.Audio.rate == rate ||
398            payload.typeSpecific.Audio.rate == 0 || rate == 0);
399  }
400
401  void UpdatePayloadRate(RtpUtility::Payload* payload,
402                         const uint32_t rate) const override {
403    payload->typeSpecific.Audio.rate = rate;
404  }
405
406  RtpUtility::Payload* CreatePayloadType(
407      const char payloadName[RTP_PAYLOAD_NAME_SIZE],
408      const int8_t payloadType,
409      const uint32_t frequency,
410      const size_t channels,
411      const uint32_t rate) const override {
412    RtpUtility::Payload* payload = new RtpUtility::Payload;
413    payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
414    strncpy(payload->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1);
415    assert(frequency >= 1000);
416    payload->typeSpecific.Audio.frequency = frequency;
417    payload->typeSpecific.Audio.channels = channels;
418    payload->typeSpecific.Audio.rate = rate;
419    payload->audio = true;
420    return payload;
421  }
422
423  int GetPayloadTypeFrequency(const RtpUtility::Payload& payload) const {
424    return payload.typeSpecific.Audio.frequency;
425  }
426};
427
428class RTPPayloadVideoStrategy : public RTPPayloadStrategy {
429 public:
430  bool CodecsMustBeUnique() const override { return false; }
431
432  bool PayloadIsCompatible(const RtpUtility::Payload& payload,
433                           const uint32_t frequency,
434                           const size_t channels,
435                           const uint32_t rate) const override {
436    return !payload.audio;
437  }
438
439  void UpdatePayloadRate(RtpUtility::Payload* payload,
440                         const uint32_t rate) const override {
441    payload->typeSpecific.Video.maxRate = rate;
442  }
443
444  RtpUtility::Payload* CreatePayloadType(
445      const char payloadName[RTP_PAYLOAD_NAME_SIZE],
446      const int8_t payloadType,
447      const uint32_t frequency,
448      const size_t channels,
449      const uint32_t rate) const override {
450    RtpVideoCodecTypes videoType = kRtpVideoGeneric;
451
452    if (RtpUtility::StringCompare(payloadName, "VP8", 3)) {
453      videoType = kRtpVideoVp8;
454    } else if (RtpUtility::StringCompare(payloadName, "VP9", 3)) {
455      videoType = kRtpVideoVp9;
456    } else if (RtpUtility::StringCompare(payloadName, "H264", 4)) {
457      videoType = kRtpVideoH264;
458    } else if (RtpUtility::StringCompare(payloadName, "I420", 4)) {
459      videoType = kRtpVideoGeneric;
460    } else if (RtpUtility::StringCompare(payloadName, "ULPFEC", 6) ||
461        RtpUtility::StringCompare(payloadName, "RED", 3)) {
462      videoType = kRtpVideoNone;
463    } else {
464      videoType = kRtpVideoGeneric;
465    }
466    RtpUtility::Payload* payload = new RtpUtility::Payload;
467
468    payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
469    strncpy(payload->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1);
470    payload->typeSpecific.Video.videoCodecType = videoType;
471    payload->typeSpecific.Video.maxRate = rate;
472    payload->audio = false;
473    return payload;
474  }
475
476  int GetPayloadTypeFrequency(const RtpUtility::Payload& payload) const {
477    return kVideoPayloadTypeFrequency;
478  }
479};
480
481RTPPayloadStrategy* RTPPayloadStrategy::CreateStrategy(
482    const bool handling_audio) {
483  if (handling_audio) {
484    return new RTPPayloadAudioStrategy();
485  } else {
486    return new RTPPayloadVideoStrategy();
487  }
488}
489
490}  // namespace webrtc
491