/*
 *  Copyright (c) 2018 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 "api/video_codecs/sdp_video_format.h"

#include <initializer_list>
#include <optional>
#include <span>
#include <string>
#include <utility>

#include "absl/container/inlined_vector.h"
#include "absl/strings/match.h"
#include "absl/strings/string_view.h"
#include "api/rtp_parameters.h"
#include "api/video/video_codec_type.h"
#include "api/video_codecs/av1_profile.h"
#include "api/video_codecs/h264_profile_level_id.h"
#include "api/video_codecs/scalability_mode.h"
#ifdef RTC_ENABLE_H265
#include "api/video_codecs/h265_profile_tier_level.h"
#endif
#include "api/video_codecs/video_codec.h"
#include "api/video_codecs/vp9_profile.h"
#include "media/base/media_constants.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/strings/string_builder.h"

namespace webrtc {

namespace {

// TODO(bugs.webrtc.org/15847): remove code duplication of IsSameCodecSpecific
// in media/base/codec.cc
std::string GetFmtpParameterOrDefault(const CodecParameterMap& params,
                                      const std::string& name,
                                      const std::string& default_value) {
  const auto it = params.find(name);
  if (it != params.end()) {
    return it->second;
  }
  return default_value;
}

std::string H264GetPacketizationModeOrDefault(const CodecParameterMap& params) {
  // If packetization-mode is not present, default to "0".
  // https://tools.ietf.org/html/rfc6184#section-6.2
  return GetFmtpParameterOrDefault(params, kH264FmtpPacketizationMode, "0");
}

bool H264IsSamePacketizationMode(const CodecParameterMap& left,
                                 const CodecParameterMap& right) {
  return H264GetPacketizationModeOrDefault(left) ==
         H264GetPacketizationModeOrDefault(right);
}

#ifdef RTC_ENABLE_H265
std::string GetH265TxModeOrDefault(const CodecParameterMap& params) {
  // If TxMode is not present, a value of "SRST" must be inferred.
  // https://tools.ietf.org/html/rfc7798@section-7.1
  return GetFmtpParameterOrDefault(params, kH265FmtpTxMode, "SRST");
}

bool IsSameH265TxMode(const CodecParameterMap& left,
                      const CodecParameterMap& right) {
  return absl::EqualsIgnoreCase(GetH265TxModeOrDefault(left),
                                GetH265TxModeOrDefault(right));
}
#endif

// Some (video) codecs are actually families of codecs and rely on parameters
// to distinguish different incompatible family members.
bool IsSameCodecSpecific(const std::string& name1,
                         const CodecParameterMap& params1,
                         const std::string& name2,
                         const CodecParameterMap& params2) {
  // The assumption when calling this function is that the two formats have the
  // same name.
  RTC_DCHECK(absl::EqualsIgnoreCase(name1, name2));

  VideoCodecType codec_type = PayloadStringToCodecType(name1);
  switch (codec_type) {
    case kVideoCodecH264:
      return H264IsSameProfile(params1, params2) &&
             H264IsSamePacketizationMode(params1, params2);
    case kVideoCodecVP9:
      return VP9IsSameProfile(params1, params2);
    case kVideoCodecAV1:
      // https://aomediacodec.github.io/av1-rtp-spec/#723-usage-with-the-sdp-offeranswer-model
      //   These media configuration parameters are asymmetrical and the
      //   answerer MAY declare its own media configuration
      // TODO(bugs.webrtc.org/396434695): for backward compability we currently
      // compare profile.
      return AV1IsSameProfile(params1, params2);
#ifdef RTC_ENABLE_H265
    case kVideoCodecH265:
      return H265IsSameProfile(params1, params2) &&
             H265IsSameTier(params1, params2) &&
             IsSameH265TxMode(params1, params2);
#endif
    default:
      return true;
  }
}

}  // namespace

SdpVideoFormat::SdpVideoFormat(absl::string_view name) : name(name) {}

SdpVideoFormat::SdpVideoFormat(absl::string_view name,
                               const CodecParameterMap& parameters)
    : name(name), parameters(parameters) {}

SdpVideoFormat::SdpVideoFormat(absl::string_view name,
                               CodecParameterMap&& parameters)
    : name(name), parameters(std::move(parameters)) {}

SdpVideoFormat::SdpVideoFormat(
    absl::string_view name,
    std::initializer_list<std::pair<absl::string_view, absl::string_view>>
        parameters)
    : name(name), parameters(parameters.begin(), parameters.end()) {}

SdpVideoFormat::SdpVideoFormat(
    absl::string_view name,
    const CodecParameterMap& parameters,
    std::span<const ScalabilityMode> scalability_modes)
    : name(name),
      parameters(parameters),
      scalability_modes(scalability_modes.begin(), scalability_modes.end()) {}

SdpVideoFormat::SdpVideoFormat(
    absl::string_view name,
    CodecParameterMap&& parameters,
    std::span<const ScalabilityMode> scalability_modes)
    : name(name),
      parameters(std::move(parameters)),
      scalability_modes(scalability_modes.begin(), scalability_modes.end()) {}

SdpVideoFormat::SdpVideoFormat(
    absl::string_view name,
    std::initializer_list<std::pair<absl::string_view, absl::string_view>>
        parameters,
    std::span<const ScalabilityMode> scalability_modes)
    : name(name),
      parameters(parameters.begin(), parameters.end()),
      scalability_modes(scalability_modes.begin(), scalability_modes.end()) {}

SdpVideoFormat::SdpVideoFormat(
    const SdpVideoFormat& format,
    std::span<const ScalabilityMode> scalability_modes)
    : name(format.name),
      parameters(format.parameters),
      scalability_modes(scalability_modes.begin(), scalability_modes.end()) {}

SdpVideoFormat::SdpVideoFormat(const SdpVideoFormat&) = default;
SdpVideoFormat::SdpVideoFormat(SdpVideoFormat&&) = default;
SdpVideoFormat& SdpVideoFormat::operator=(const SdpVideoFormat&) = default;
SdpVideoFormat& SdpVideoFormat::operator=(SdpVideoFormat&&) = default;

SdpVideoFormat::~SdpVideoFormat() = default;

std::string SdpVideoFormat::ToString() const {
  StringBuilder builder;
  builder << "Codec name: " << name << ", parameters: {";
  for (const auto& kv : parameters) {
    builder << " " << kv.first << "=" << kv.second;
  }

  builder << " }";
  if (!scalability_modes.empty()) {
    builder << ", scalability_modes: [";
    bool first = true;
    for (const auto scalability_mode : scalability_modes) {
      if (first) {
        first = false;
      } else {
        builder << ", ";
      }
      builder << ScalabilityModeToString(scalability_mode);
    }
    builder << "]";
  }

  if (packetization) {
    builder << ", packetization: " << *packetization;
  }
  if (tx_mode) {
    builder << ", tx_mode: " << *tx_mode;
  }

  return builder.Release();
}

bool SdpVideoFormat::IsSameCodec(const SdpVideoFormat& other) const {
  // Two codecs are considered the same if the name matches (case insensitive)
  // and certain codec-specific parameters match.
  return absl::EqualsIgnoreCase(name, other.name) &&
         IsSameCodecSpecific(name, parameters, other.name, other.parameters);
}

bool SdpVideoFormat::IsCodecInList(
    std::span<const SdpVideoFormat> formats) const {
  for (const auto& format : formats) {
    if (IsSameCodec(format)) {
      return true;
    }
  }
  return false;
}

bool operator==(const SdpVideoFormat& a, const SdpVideoFormat& b) {
  return a.name == b.name && a.parameters == b.parameters &&
         a.scalability_modes == b.scalability_modes &&
         a.packetization == b.packetization && a.tx_mode == b.tx_mode;
}

const SdpVideoFormat SdpVideoFormat::VP8() {
  return SdpVideoFormat(kVp8CodecName, {});
}

const SdpVideoFormat SdpVideoFormat::H264() {
  // H264 will typically require more tweaking like setting
  // * packetization-mode (which defaults to 0 but 1 is more common)
  // * level-asymmetry-allowed (which defaults to 0 but 1 is more common)
  // * profile-level-id of which there are many.
  return SdpVideoFormat(kH264CodecName, {});
}

const SdpVideoFormat SdpVideoFormat::H265() {
  return SdpVideoFormat(kH265CodecName, {});
}

const SdpVideoFormat SdpVideoFormat::VP9Profile0() {
  return SdpVideoFormat(
      kVp9CodecName,
      {{kVP9FmtpProfileId, VP9ProfileToString(VP9Profile::kProfile0)}});
}

const SdpVideoFormat SdpVideoFormat::VP9Profile1() {
  return SdpVideoFormat(
      kVp9CodecName,
      {{kVP9FmtpProfileId, VP9ProfileToString(VP9Profile::kProfile1)}});
}

const SdpVideoFormat SdpVideoFormat::VP9Profile2() {
  return SdpVideoFormat(
      kVp9CodecName,
      {{kVP9FmtpProfileId, VP9ProfileToString(VP9Profile::kProfile2)}});
}

const SdpVideoFormat SdpVideoFormat::VP9Profile3() {
  return SdpVideoFormat(
      kVp9CodecName,
      {{kVP9FmtpProfileId, VP9ProfileToString(VP9Profile::kProfile3)}});
}

const SdpVideoFormat SdpVideoFormat::AV1Profile0() {
  // https://aomediacodec.github.io/av1-rtp-spec/#72-sdp-parameters
  return SdpVideoFormat(
      kAv1CodecName,
      {{kAv1FmtpProfile, AV1ProfileToString(AV1Profile::kProfile0).data()},
       {kAv1FmtpLevelIdx, "5"},
       {kAv1FmtpTier, "0"}});
}

const SdpVideoFormat SdpVideoFormat::AV1Profile1() {
  // https://aomediacodec.github.io/av1-rtp-spec/#72-sdp-parameters
  return SdpVideoFormat(
      kAv1CodecName,
      {{kAv1FmtpProfile, AV1ProfileToString(AV1Profile::kProfile1).data()},
       {kAv1FmtpLevelIdx, "5"},
       {kAv1FmtpTier, "0"}});
}

std::optional<SdpVideoFormat> FuzzyMatchSdpVideoFormat(
    std::span<const SdpVideoFormat> supported_formats,
    const SdpVideoFormat& format) {
  std::optional<SdpVideoFormat> res;
  int best_parameter_match = 0;
  for (const auto& supported_format : supported_formats) {
    if (absl::EqualsIgnoreCase(supported_format.name, format.name)) {
      int matching_parameters = 0;
      for (const auto& kv : supported_format.parameters) {
        auto it = format.parameters.find(kv.first);
        if (it != format.parameters.end() && it->second == kv.second) {
          matching_parameters += 1;
        }
      }

      if (!res || matching_parameters > best_parameter_match) {
        res = supported_format;
        best_parameter_match = matching_parameters;
      }
    }
  }

  if (!res) {
    RTC_LOG(LS_INFO) << "Failed to match SdpVideoFormat " << format.ToString();
  } else if (*res != format) {
    RTC_LOG(LS_INFO) << "Matched SdpVideoFormat " << format.ToString()
                     << " with " << res->ToString();
  }

  return res;
}

}  // namespace webrtc
