/*
 *  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 "absl/strings/ascii.h"
#include "api/audio_codecs/audio_format.h"
#include "media/base/codec.h"
#include "media/base/media_constants.h"

namespace cricket {

webrtc::SdpAudioFormat AudioCodecToSdpAudioFormat(const Codec& 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.
           {{kPcmuCodecName, 8000, 1}, 0},
           {{"GSM", 8000, 1}, 3},
           {{"G723", 8000, 1}, 4},
           {{"DVI4", 8000, 1}, 5},
           {{"DVI4", 16000, 1}, 6},
           {{"LPC", 8000, 1}, 7},
           {{kPcmaCodecName, 8000, 1}, 8},
           {{kG722CodecName, 8000, 1}, 9},
           {{kL16CodecName, 44100, 2}, 10},
           {{kL16CodecName, 44100, 1}, 11},
           {{"QCELP", 8000, 1}, 12},
           {{kCnCodecName, 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)
           {{kIlbcCodecName, 8000, 1}, 102},
           {{kCnCodecName, 16000, 1}, 105},
           {{kCnCodecName, 32000, 1}, 106},
           {{kOpusCodecName,
             48000,
             2,
             {{kCodecParamMinPTime, "10"},
              {kCodecParamUseInbandFec, kParamValueTrue}}},
            111},
           // RED for opus is assigned in the lower range, starting at the top.
           // Note that the FMTP refers to the opus payload type.
           {{kRedCodecName,
             48000,
             2,
             {{kCodecParamNotInNameValueFormat, "111/111"}}},
            63},
           // 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<Codec> 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) {
    Codec codec =
        cricket::CreateAudioCodec(*opt_payload_type, format.name,
                                  format.clockrate_hz, 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 =
          absl::AsciiStrToLower(a.name).compare(absl::AsciiStrToLower(b.name));
      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
