15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  Use of this source code is governed by a BSD-style license
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *  that can be found in the LICENSE file in the root of the source
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *  tree. An additional intellectual property rights grant can be found
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  in the file PATENTS.  All contributing project authors may
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  be found in the AUTHORS file in the root of the source tree.
9ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch */
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "webrtc/system_wrappers/interface/logging.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace webrtc {
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RTPPayloadRegistry::RTPPayloadRegistry(
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RTPPayloadStrategy* rtp_payload_strategy)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rtp_payload_strategy_(rtp_payload_strategy),
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      red_payload_type_(-1),
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ulpfec_payload_type_(-1),
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      incoming_payload_type_(-1),
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      last_received_payload_type_(-1),
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      last_received_media_payload_type_(-1),
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rtx_(false),
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      payload_type_rtx_(-1),
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ssrc_rtx_(0) {}
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RTPPayloadRegistry::~RTPPayloadRegistry() {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (!payload_type_map_.empty()) {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RtpUtility::PayloadTypeMap::iterator it = payload_type_map_.begin();
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete it->second;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    payload_type_map_.erase(it);
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t RTPPayloadRegistry::RegisterReceivePayload(
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char payload_name[RTP_PAYLOAD_NAME_SIZE],
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int8_t payload_type,
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const uint32_t frequency,
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const uint8_t channels,
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const uint32_t rate,
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool* created_new_payload) {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(payload_type >= 0);
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(payload_name);
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *created_new_payload = false;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Sanity check.
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (payload_type) {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Reserved payload types to avoid RTCP conflicts when marker bit is set.
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 64:        //  192 Full INTRA-frame request.
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 72:        //  200 Sender report.
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 73:        //  201 Receiver report.
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 74:        //  202 Source description.
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 75:        //  203 Goodbye.
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 76:        //  204 Application-defined.
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 77:        //  205 Transport layer FB message.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 78:        //  206 Payload-specific FB message.
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 79:        //  207 Extended report.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(LS_ERROR) << "Can't register invalid receiver payload type: "
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    << payload_type;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return -1;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t payload_name_length = strlen(payload_name);
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CriticalSectionScoped cs(crit_sect_.get());
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtpUtility::PayloadTypeMap::iterator it =
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      payload_type_map_.find(payload_type);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it != payload_type_map_.end()) {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We already use this payload type.
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RtpUtility::Payload* payload = it->second;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert(payload);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t name_length = strlen(payload->name);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Check if it's the same as we already have.
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If same, ignore sending an error.
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (payload_name_length == name_length &&
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RtpUtility::StringCompare(
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            payload->name, payload_name, payload_name_length)) {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (rtp_payload_strategy_->PayloadIsCompatible(*payload, frequency,
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                     channels, rate)) {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rtp_payload_strategy_->UpdatePayloadRate(payload, rate);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return 0;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(LS_ERROR) << "Payload type already registered: " << payload_type;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rtp_payload_strategy_->CodecsMustBeUnique()) {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType(
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        payload_name, payload_name_length, frequency, channels, rate);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtpUtility::Payload* payload = NULL;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Save the RED payload type. Used in both audio and video.
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (RtpUtility::StringCompare(payload_name, "red", 3)) {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    red_payload_type_ = payload_type;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    payload = new RtpUtility::Payload;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(payload, 0, sizeof(*payload));
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    payload->audio = false;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    strncpy(payload->name, payload_name, RTP_PAYLOAD_NAME_SIZE - 1);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (RtpUtility::StringCompare(payload_name, "ulpfec", 3)) {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ulpfec_payload_type_ = payload_type;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    payload = new RtpUtility::Payload;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(payload, 0, sizeof(*payload));
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    payload->audio = false;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    strncpy(payload->name, payload_name, RTP_PAYLOAD_NAME_SIZE - 1);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *created_new_payload = true;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    payload = rtp_payload_strategy_->CreatePayloadType(
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        payload_name, payload_type, frequency, channels, rate);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload_type_map_[payload_type] = payload;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Successful set of payload type, clear the value of last received payload
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // type since it might mean something else.
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_received_payload_type_ = -1;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_received_media_payload_type_ = -1;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t RTPPayloadRegistry::DeRegisterReceivePayload(
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int8_t payload_type) {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CriticalSectionScoped cs(crit_sect_.get());
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtpUtility::PayloadTypeMap::iterator it =
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      payload_type_map_.find(payload_type);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(it != payload_type_map_.end());
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete it->second;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  payload_type_map_.erase(it);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// There can't be several codecs with the same rate, frequency and channels
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for audio codecs, but there can for video.
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Always called from within a critical section.
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RTPPayloadRegistry::DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType(
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char payload_name[RTP_PAYLOAD_NAME_SIZE],
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const size_t payload_name_length,
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const uint32_t frequency,
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const uint8_t channels,
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const uint32_t rate) {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtpUtility::PayloadTypeMap::iterator iterator = payload_type_map_.begin();
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (; iterator != payload_type_map_.end(); ++iterator) {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RtpUtility::Payload* payload = iterator->second;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t name_length = strlen(payload->name);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (payload_name_length == name_length &&
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RtpUtility::StringCompare(
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            payload->name, payload_name, payload_name_length)) {
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We found the payload name in the list.
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If audio, check frequency and rate.
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (payload->audio) {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (rtp_payload_strategy_->PayloadIsCompatible(*payload, frequency,
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                       channels, rate)) {
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Remove old setting.
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          delete payload;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          payload_type_map_.erase(iterator);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (RtpUtility::StringCompare(payload_name, "red", 3)) {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delete payload;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        payload_type_map_.erase(iterator);
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
175    }
176  }
177}
178
179int32_t RTPPayloadRegistry::ReceivePayloadType(
180    const char payload_name[RTP_PAYLOAD_NAME_SIZE],
181    const uint32_t frequency,
182    const uint8_t channels,
183    const uint32_t rate,
184    int8_t* payload_type) const {
185  assert(payload_type);
186  size_t payload_name_length = strlen(payload_name);
187
188  CriticalSectionScoped cs(crit_sect_.get());
189
190  RtpUtility::PayloadTypeMap::const_iterator it = payload_type_map_.begin();
191
192  for (; it != payload_type_map_.end(); ++it) {
193    RtpUtility::Payload* payload = it->second;
194    assert(payload);
195
196    size_t name_length = strlen(payload->name);
197    if (payload_name_length == name_length &&
198        RtpUtility::StringCompare(
199            payload->name, payload_name, payload_name_length)) {
200      // Name matches.
201      if (payload->audio) {
202        if (rate == 0) {
203          // [default] audio, check freq and channels.
204          if (payload->typeSpecific.Audio.frequency == frequency &&
205              payload->typeSpecific.Audio.channels == channels) {
206            *payload_type = it->first;
207            return 0;
208          }
209        } else {
210          // Non-default audio, check freq, channels and rate.
211          if (payload->typeSpecific.Audio.frequency == frequency &&
212              payload->typeSpecific.Audio.channels == channels &&
213              payload->typeSpecific.Audio.rate == rate) {
214            // extra rate condition added
215            *payload_type = it->first;
216            return 0;
217          }
218        }
219      } else {
220        // Video.
221        *payload_type = it->first;
222        return 0;
223      }
224    }
225  }
226  return -1;
227}
228
229bool RTPPayloadRegistry::RtxEnabled() const {
230  CriticalSectionScoped cs(crit_sect_.get());
231  return rtx_;
232}
233
234bool RTPPayloadRegistry::IsRtx(const RTPHeader& header) const {
235  CriticalSectionScoped cs(crit_sect_.get());
236  return IsRtxInternal(header);
237}
238
239bool RTPPayloadRegistry::IsRtxInternal(const RTPHeader& header) const {
240  return rtx_ && ssrc_rtx_ == header.ssrc;
241}
242
243bool RTPPayloadRegistry::RestoreOriginalPacket(uint8_t** restored_packet,
244                                               const uint8_t* packet,
245                                               int* packet_length,
246                                               uint32_t original_ssrc,
247                                               const RTPHeader& header) const {
248  if (kRtxHeaderSize + header.headerLength > *packet_length) {
249    return false;
250  }
251  const uint8_t* rtx_header = packet + header.headerLength;
252  uint16_t original_sequence_number = (rtx_header[0] << 8) + rtx_header[1];
253
254  // Copy the packet into the restored packet, except for the RTX header.
255  memcpy(*restored_packet, packet, header.headerLength);
256  memcpy(*restored_packet + header.headerLength,
257         packet + header.headerLength + kRtxHeaderSize,
258         *packet_length - header.headerLength - kRtxHeaderSize);
259  *packet_length -= kRtxHeaderSize;
260
261  // Replace the SSRC and the sequence number with the originals.
262  RtpUtility::AssignUWord16ToBuffer(*restored_packet + 2,
263                                    original_sequence_number);
264  RtpUtility::AssignUWord32ToBuffer(*restored_packet + 8, original_ssrc);
265
266  CriticalSectionScoped cs(crit_sect_.get());
267
268  if (payload_type_rtx_ != -1) {
269    if (header.payloadType == payload_type_rtx_ &&
270        incoming_payload_type_ != -1) {
271      (*restored_packet)[1] = static_cast<uint8_t>(incoming_payload_type_);
272      if (header.markerBit) {
273        (*restored_packet)[1] |= kRtpMarkerBitMask;  // Marker bit is set.
274      }
275    } else {
276      LOG(LS_WARNING) << "Incorrect RTX configuration, dropping packet.";
277      return false;
278    }
279  }
280  return true;
281}
282
283void RTPPayloadRegistry::SetRtxSsrc(uint32_t ssrc) {
284  CriticalSectionScoped cs(crit_sect_.get());
285  ssrc_rtx_ = ssrc;
286  rtx_ = true;
287}
288
289void RTPPayloadRegistry::SetRtxPayloadType(int payload_type) {
290  CriticalSectionScoped cs(crit_sect_.get());
291  assert(payload_type >= 0);
292  payload_type_rtx_ = payload_type;
293  rtx_ = true;
294}
295
296bool RTPPayloadRegistry::IsRed(const RTPHeader& header) const {
297  CriticalSectionScoped cs(crit_sect_.get());
298  return red_payload_type_ == header.payloadType;
299}
300
301bool RTPPayloadRegistry::IsEncapsulated(const RTPHeader& header) const {
302  return IsRed(header) || IsRtx(header);
303}
304
305bool RTPPayloadRegistry::GetPayloadSpecifics(uint8_t payload_type,
306                                             PayloadUnion* payload) const {
307  CriticalSectionScoped cs(crit_sect_.get());
308  RtpUtility::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
319int RTPPayloadRegistry::GetPayloadTypeFrequency(
320    uint8_t payload_type) const {
321  RtpUtility::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
329bool RTPPayloadRegistry::PayloadTypeToPayload(
330    const uint8_t payload_type,
331    RtpUtility::Payload*& payload) const {
332  CriticalSectionScoped cs(crit_sect_.get());
333
334  RtpUtility::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
346void RTPPayloadRegistry::SetIncomingPayloadType(const RTPHeader& header) {
347  CriticalSectionScoped cs(crit_sect_.get());
348  if (!IsRtxInternal(header))
349    incoming_payload_type_ = header.payloadType;
350}
351
352bool 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
362class RTPPayloadAudioStrategy : public RTPPayloadStrategy {
363 public:
364  virtual bool CodecsMustBeUnique() const OVERRIDE { return true; }
365
366  virtual bool PayloadIsCompatible(const RtpUtility::Payload& payload,
367                                   const uint32_t frequency,
368                                   const uint8_t channels,
369                                   const uint32_t rate) const OVERRIDE {
370    return
371        payload.audio &&
372        payload.typeSpecific.Audio.frequency == frequency &&
373        payload.typeSpecific.Audio.channels == channels &&
374        (payload.typeSpecific.Audio.rate == rate ||
375            payload.typeSpecific.Audio.rate == 0 || rate == 0);
376  }
377
378  virtual void UpdatePayloadRate(RtpUtility::Payload* payload,
379                                 const uint32_t rate) const OVERRIDE {
380    payload->typeSpecific.Audio.rate = rate;
381  }
382
383  virtual RtpUtility::Payload* CreatePayloadType(
384      const char payloadName[RTP_PAYLOAD_NAME_SIZE],
385      const int8_t payloadType,
386      const uint32_t frequency,
387      const uint8_t channels,
388      const uint32_t rate) const OVERRIDE {
389    RtpUtility::Payload* payload = new RtpUtility::Payload;
390    payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
391    strncpy(payload->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1);
392    assert(frequency >= 1000);
393    payload->typeSpecific.Audio.frequency = frequency;
394    payload->typeSpecific.Audio.channels = channels;
395    payload->typeSpecific.Audio.rate = rate;
396    payload->audio = true;
397    return payload;
398  }
399
400  int GetPayloadTypeFrequency(const RtpUtility::Payload& payload) const {
401    return payload.typeSpecific.Audio.frequency;
402  }
403};
404
405class RTPPayloadVideoStrategy : public RTPPayloadStrategy {
406 public:
407  virtual bool CodecsMustBeUnique() const OVERRIDE { return false; }
408
409  virtual bool PayloadIsCompatible(const RtpUtility::Payload& payload,
410                                   const uint32_t frequency,
411                                   const uint8_t channels,
412                                   const uint32_t rate) const OVERRIDE {
413    return !payload.audio;
414  }
415
416  virtual void UpdatePayloadRate(RtpUtility::Payload* payload,
417                                 const uint32_t rate) const OVERRIDE {
418    payload->typeSpecific.Video.maxRate = rate;
419  }
420
421  virtual RtpUtility::Payload* CreatePayloadType(
422      const char payloadName[RTP_PAYLOAD_NAME_SIZE],
423      const int8_t payloadType,
424      const uint32_t frequency,
425      const uint8_t channels,
426      const uint32_t rate) const OVERRIDE {
427    RtpVideoCodecTypes videoType = kRtpVideoGeneric;
428    if (RtpUtility::StringCompare(payloadName, "VP8", 3)) {
429      videoType = kRtpVideoVp8;
430    } else if (RtpUtility::StringCompare(payloadName, "H264", 4)) {
431      videoType = kRtpVideoH264;
432    } else if (RtpUtility::StringCompare(payloadName, "I420", 4)) {
433      videoType = kRtpVideoGeneric;
434    } else if (RtpUtility::StringCompare(payloadName, "ULPFEC", 6)) {
435      videoType = kRtpVideoNone;
436    } else {
437      videoType = kRtpVideoGeneric;
438    }
439    RtpUtility::Payload* payload = new RtpUtility::Payload;
440
441    payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
442    strncpy(payload->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1);
443    payload->typeSpecific.Video.videoCodecType = videoType;
444    payload->typeSpecific.Video.maxRate = rate;
445    payload->audio = false;
446    return payload;
447  }
448
449  int GetPayloadTypeFrequency(const RtpUtility::Payload& payload) const {
450    return kVideoPayloadTypeFrequency;
451  }
452};
453
454RTPPayloadStrategy* RTPPayloadStrategy::CreateStrategy(
455    const bool handling_audio) {
456  if (handling_audio) {
457    return new RTPPayloadAudioStrategy();
458  } else {
459    return new RTPPayloadVideoStrategy();
460  }
461}
462
463}  // namespace webrtc
464