/*
 *  Copyright (c) 2012 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/video_codec.h"

#include <cstring>
#include <optional>
#include <string>

#include "absl/strings/match.h"
#include "api/video/video_codec_type.h"
#include "api/video_codecs/scalability_mode.h"
#include "api/video_codecs/sdp_video_format.h"
#include "api/video_codecs/simulcast_stream.h"
#include "rtc_base/checks.h"
#include "rtc_base/strings/string_builder.h"

namespace webrtc {
namespace {
constexpr char kPayloadNameVp8[] = "VP8";
constexpr char kPayloadNameVp9[] = "VP9";
constexpr char kPayloadNameAv1[] = "AV1";
// TODO(bugs.webrtc.org/13166): Remove AV1X when backwards compatibility is not
// needed.
constexpr char kPayloadNameAv1x[] = "AV1X";
constexpr char kPayloadNameH264[] = "H264";
constexpr char kPayloadNameGeneric[] = "Generic";
constexpr char kPayloadNameH265[] = "H265";
}  // namespace

bool VideoCodecVP8::operator==(const VideoCodecVP8& other) const {
  return (numberOfTemporalLayers == other.numberOfTemporalLayers &&
          denoisingOn == other.denoisingOn &&
          automaticResizeOn == other.automaticResizeOn &&
          keyFrameInterval == other.keyFrameInterval);
}

bool VideoCodecVP9::operator==(const VideoCodecVP9& other) const {
  return (numberOfTemporalLayers == other.numberOfTemporalLayers &&
          denoisingOn == other.denoisingOn &&
          keyFrameInterval == other.keyFrameInterval &&
          adaptiveQpMode == other.adaptiveQpMode &&
          automaticResizeOn == other.automaticResizeOn &&
          numberOfSpatialLayers == other.numberOfSpatialLayers &&
          flexibleMode == other.flexibleMode);
}

bool VideoCodecH264::operator==(const VideoCodecH264& other) const {
  return (keyFrameInterval == other.keyFrameInterval &&
          numberOfTemporalLayers == other.numberOfTemporalLayers);
}

VideoCodec::VideoCodec()
    : codecType(kVideoCodecGeneric),
      width(0),
      height(0),
      startBitrate(0),
      maxBitrate(0),
      minBitrate(0),
      maxFramerate(0),
      active(true),
      qpMax(0),
      numberOfSimulcastStreams(0),
      simulcastStream(),
      spatialLayers(),
      mode(VideoCodecMode::kRealtimeVideo),
      expect_encode_from_texture(false),
      timing_frame_thresholds({.delay_ms = 0, .outlier_ratio_percent = 0}),
      legacy_conference_mode(false),
      codec_specific_(),
      complexity_(VideoCodecComplexity::kComplexityNormal) {}

std::string VideoCodec::ToString() const {
  char string_buf[2048];
  SimpleStringBuilder ss(string_buf);

  ss << "VideoCodec {" << "type: " << CodecTypeToPayloadString(codecType)
     << ", mode: "
     << (mode == VideoCodecMode::kRealtimeVideo ? "RealtimeVideo"
                                                : "Screensharing");
  if (IsSinglecast()) {
    ss << ", Singlecast: {" << width << "x" << height << " "
       << ScalabilityModeToString(GetScalabilityMode())
       << (active ? ", active" : ", inactive") << "}";
  } else {
    ss << ", Simulcast: {";
    for (size_t i = 0; i < numberOfSimulcastStreams; ++i) {
      const SimulcastStream stream = simulcastStream[i];
      ss << "[" << stream.width << "x" << stream.height << " "
         << ScalabilityModeToString(stream.GetScalabilityMode())
         << (stream.active ? ", active" : ", inactive") << "]";
    }
    ss << "}";
  }
  ss << "}";
  return ss.str();
}

VideoCodecVP8* VideoCodec::VP8() {
  RTC_DCHECK_EQ(codecType, kVideoCodecVP8);
  return &codec_specific_.VP8;
}

const VideoCodecVP8& VideoCodec::VP8() const {
  RTC_DCHECK_EQ(codecType, kVideoCodecVP8);
  return codec_specific_.VP8;
}

VideoCodecVP9* VideoCodec::VP9() {
  RTC_DCHECK_EQ(codecType, kVideoCodecVP9);
  return &codec_specific_.VP9;
}

const VideoCodecVP9& VideoCodec::VP9() const {
  RTC_DCHECK_EQ(codecType, kVideoCodecVP9);
  return codec_specific_.VP9;
}

VideoCodecH264* VideoCodec::H264() {
  RTC_DCHECK_EQ(codecType, kVideoCodecH264);
  return &codec_specific_.H264;
}

const VideoCodecH264& VideoCodec::H264() const {
  RTC_DCHECK_EQ(codecType, kVideoCodecH264);
  return codec_specific_.H264;
}

VideoCodecAV1* VideoCodec::AV1() {
  RTC_DCHECK_EQ(codecType, kVideoCodecAV1);
  return &codec_specific_.AV1;
}

const VideoCodecAV1& VideoCodec::AV1() const {
  RTC_DCHECK_EQ(codecType, kVideoCodecAV1);
  return codec_specific_.AV1;
}

const char* CodecTypeToPayloadString(VideoCodecType type) {
  switch (type) {
    case kVideoCodecVP8:
      return kPayloadNameVp8;
    case kVideoCodecVP9:
      return kPayloadNameVp9;
    case kVideoCodecAV1:
      return kPayloadNameAv1;
    case kVideoCodecH264:
      return kPayloadNameH264;
    case kVideoCodecGeneric:
      return kPayloadNameGeneric;
    case kVideoCodecH265:
      return kPayloadNameH265;
  }
  RTC_CHECK_NOTREACHED();
}

VideoCodecType PayloadStringToCodecType(const std::string& name) {
  if (absl::EqualsIgnoreCase(name, kPayloadNameVp8))
    return kVideoCodecVP8;
  if (absl::EqualsIgnoreCase(name, kPayloadNameVp9))
    return kVideoCodecVP9;
  if (absl::EqualsIgnoreCase(name, kPayloadNameAv1) ||
      absl::EqualsIgnoreCase(name, kPayloadNameAv1x))
    return kVideoCodecAV1;
  if (absl::EqualsIgnoreCase(name, kPayloadNameH264))
    return kVideoCodecH264;
  if (absl::EqualsIgnoreCase(name, kPayloadNameH265))
    return kVideoCodecH265;
  return kVideoCodecGeneric;
}

VideoCodecComplexity VideoCodec::GetVideoEncoderComplexity() const {
  return complexity_;
}

void VideoCodec::SetVideoEncoderComplexity(
    VideoCodecComplexity complexity_setting) {
  complexity_ = complexity_setting;
}

bool VideoCodec::GetFrameDropEnabled() const {
  return frame_drop_enabled_;
}

void VideoCodec::SetFrameDropEnabled(bool enabled) {
  frame_drop_enabled_ = enabled;
}

bool VideoCodec::IsMixedCodec() const {
  std::optional<SdpVideoFormat> first_format;
  for (size_t i = 0; i < numberOfSimulcastStreams; ++i) {
    if (!simulcastStream[i].active) {
      continue;
    }
    if (!simulcastStream[i].format.has_value()) {
      return false;  // Format is always set for active layers in mixed-codec.
    }
    if (!first_format.has_value()) {
      first_format = simulcastStream[i].format;  // First active layer's format.
    } else if (!first_format->IsSameCodec(*simulcastStream[i].format)) {
      return true;
    }
  }
  return false;
}

}  // namespace webrtc
