/*
 *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "media/engine/payload_type_mapper.h"

#include <utility>

#include "api/audio_codecs/audio_format.h"
#include "common_types.h"  // NOLINT(build/include)
#include "media/base/mediaconstants.h"

namespace cricket {

webrtc::SdpAudioFormat AudioCodecToSdpAudioFormat(const AudioCodec& ac) {
  return webrtc::SdpAudioFormat(ac.name, ac.clockrate, ac.channels, ac.params);
}

PayloadTypeMapper::PayloadTypeMapper()
    // RFC 3551 reserves payload type numbers in the range 96-127 exclusively
    // for dynamic assignment. Once those are used up, it is recommended that
    // payload types unassigned by the RFC are used for dynamic payload type
    // mapping, before any static payload ids. At this point, we only support
    // mapping within the exclusive range.
    : next_unused_payload_type_(96),
      max_payload_type_(127),
      mappings_({
          // Static payload type assignments according to RFC 3551.
          {{"PCMU",   8000, 1}, 0},
          {{"GSM",    8000, 1}, 3},
          {{"G723",   8000, 1}, 4},
          {{"DVI4",   8000, 1}, 5},
          {{"DVI4",  16000, 1}, 6},
          {{"LPC",    8000, 1}, 7},
          {{"PCMA",   8000, 1}, 8},
          {{"G722",   8000, 1}, 9},
          {{"L16",   44100, 2}, 10},
          {{"L16",   44100, 1}, 11},
          {{"QCELP",  8000, 1}, 12},
          {{"CN",     8000, 1}, 13},
          // RFC 4566 is a bit ambiguous on the contents of the "encoding
          // parameters" field, which, for audio, encodes the number of
          // channels. It is "optional and may be omitted if the number of
          // channels is one". Does that necessarily imply that an omitted
          // encoding parameter means one channel?  Since RFC 3551 doesn't
          // specify a value for this parameter for MPA, I've included both 0
          // and 1 here, to increase the chances it will be correctly used if
          // someone implements an MPEG audio encoder/decoder.
          {{"MPA",   90000, 0}, 14},
          {{"MPA",   90000, 1}, 14},
          {{"G728",   8000, 1}, 15},
          {{"DVI4",  11025, 1}, 16},
          {{"DVI4",  22050, 1}, 17},
          {{"G729",   8000, 1}, 18},

          // Payload type assignments currently used by WebRTC.
          // Includes data to reduce collisions (and thus reassignments)
          {{kGoogleRtpDataCodecName, 0, 0}, kGoogleRtpDataCodecPlType},
          {{kIlbcCodecName,    8000, 1}, 102},
          {{kIsacCodecName,   16000, 1}, 103},
          {{kIsacCodecName,   32000, 1}, 104},
          {{kCnCodecName,     16000, 1}, 105},
          {{kCnCodecName,     32000, 1}, 106},
          {{kGoogleSctpDataCodecName, 0, 0}, kGoogleSctpDataCodecPlType},
          {{kOpusCodecName,   48000, 2,
              {{"minptime", "10"}, {"useinbandfec", "1"}}}, 111},
          // TODO(solenberg): Remove the hard coded 16k,32k,48k DTMF once we
          // assign payload types dynamically for send side as well.
          {{kDtmfCodecName,   48000, 1}, 110},
          {{kDtmfCodecName,   32000, 1}, 112},
          {{kDtmfCodecName,   16000, 1}, 113},
          {{kDtmfCodecName,    8000, 1}, 126}}) {
  // TODO(ossu): Try to keep this as change-proof as possible until we're able
  // to remove the payload type constants from everywhere in the code.
  for (const auto& mapping : mappings_) {
    used_payload_types_.insert(mapping.second);
  }
}

PayloadTypeMapper::~PayloadTypeMapper() = default;

absl::optional<int> PayloadTypeMapper::GetMappingFor(
    const webrtc::SdpAudioFormat& format) {
  auto iter = mappings_.find(format);
  if (iter != mappings_.end())
    return iter->second;

  for (; next_unused_payload_type_ <= max_payload_type_;
       ++next_unused_payload_type_) {
    int payload_type = next_unused_payload_type_;
    if (used_payload_types_.find(payload_type) == used_payload_types_.end()) {
      used_payload_types_.insert(payload_type);
      mappings_[format] = payload_type;
      ++next_unused_payload_type_;
      return payload_type;
    }
  }

  return absl::nullopt;
}

absl::optional<int> PayloadTypeMapper::FindMappingFor(
    const webrtc::SdpAudioFormat& format) const {
  auto iter = mappings_.find(format);
  if (iter != mappings_.end())
    return iter->second;

  return absl::nullopt;
}

absl::optional<AudioCodec> PayloadTypeMapper::ToAudioCodec(
    const webrtc::SdpAudioFormat& format) {
  // TODO(ossu): We can safely set bitrate to zero here, since that field is
  // not presented in the SDP. It is used to ferry around some target bitrate
  // values for certain codecs (ISAC and Opus) and in ways it really
  // shouldn't. It should be removed once we no longer use CodecInsts in the
  // ACM or NetEq.
  auto opt_payload_type = GetMappingFor(format);
  if (opt_payload_type) {
    AudioCodec codec(*opt_payload_type, format.name, format.clockrate_hz, 0,
                     format.num_channels);
    codec.params = format.parameters;
    return std::move(codec);
  }

  return absl::nullopt;
}

bool PayloadTypeMapper::SdpAudioFormatOrdering::operator()(
    const webrtc::SdpAudioFormat& a,
    const webrtc::SdpAudioFormat& b) const {
  if (a.clockrate_hz == b.clockrate_hz) {
    if (a.num_channels == b.num_channels) {
      int name_cmp = STR_CASE_CMP(a.name.c_str(), b.name.c_str());
      if (name_cmp == 0)
        return a.parameters < b.parameters;
      return name_cmp < 0;
    }
    return a.num_channels < b.num_channels;
  }
  return a.clockrate_hz < b.clockrate_hz;
}

}  // namespace cricket
