/*
 *  Copyright (c) 2014 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 "test/encoder_settings.h"

#include <algorithm>
#include <cstddef>
#include <string>
#include <vector>

#include "api/field_trials_view.h"
#include "api/make_ref_counted.h"
#include "api/scoped_refptr.h"
#include "api/video/video_codec_type.h"
#include "api/video_codecs/sdp_video_format.h"
#include "call/rtp_config.h"
#include "call/video_receive_stream.h"
#include "call/video_send_stream.h"
#include "rtc_base/checks.h"
#include "video/config/video_encoder_config.h"

namespace webrtc {
namespace test {

const size_t DefaultVideoStreamFactory::kMaxNumberOfStreams;
const int DefaultVideoStreamFactory::kMaxBitratePerStream[] = {150000, 450000,
                                                               1500000};
const int DefaultVideoStreamFactory::kDefaultMinBitratePerStream[] = {
    30000, 200000, 700000};

// static
std::vector<VideoStream> CreateVideoStreams(
    int width,
    int height,
    const VideoEncoderConfig& encoder_config) {
  RTC_DCHECK(encoder_config.number_of_streams <=
             DefaultVideoStreamFactory::kMaxNumberOfStreams);

  std::vector<VideoStream> stream_settings(encoder_config.number_of_streams);

  int bitrate_left_bps = 0;
  if (encoder_config.max_bitrate_bps > 0) {
    bitrate_left_bps = encoder_config.max_bitrate_bps;
  } else {
    for (size_t stream_num = 0; stream_num < encoder_config.number_of_streams;
         ++stream_num) {
      bitrate_left_bps +=
          DefaultVideoStreamFactory::kMaxBitratePerStream[stream_num];
    }
  }

  for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
    stream_settings[i].width =
        (i + 1) * width / encoder_config.number_of_streams;
    stream_settings[i].height =
        (i + 1) * height / encoder_config.number_of_streams;
    stream_settings[i].max_framerate = 30;
    stream_settings[i].max_qp = 56;
    stream_settings[i].min_bitrate_bps =
        DefaultVideoStreamFactory::kDefaultMinBitratePerStream[i];

    // Use configured values instead of default values if set.
    const VideoStream stream = (i < encoder_config.simulcast_layers.size())
                                   ? encoder_config.simulcast_layers[i]
                                   : VideoStream();

    int max_bitrate_bps =
        stream.max_bitrate_bps > 0
            ? stream.max_bitrate_bps
            : DefaultVideoStreamFactory::kMaxBitratePerStream[i];
    max_bitrate_bps = std::min(bitrate_left_bps, max_bitrate_bps);

    int target_bitrate_bps = stream.target_bitrate_bps > 0
                                 ? stream.target_bitrate_bps
                                 : max_bitrate_bps;
    target_bitrate_bps = std::min(max_bitrate_bps, target_bitrate_bps);

    if (stream.min_bitrate_bps > 0) {
      RTC_DCHECK_LE(stream.min_bitrate_bps, target_bitrate_bps);
      stream_settings[i].min_bitrate_bps = stream.min_bitrate_bps;
    }
    if (stream.max_framerate > 0) {
      stream_settings[i].max_framerate = stream.max_framerate;
    }
    if (stream.num_temporal_layers) {
      RTC_DCHECK_GE(*stream.num_temporal_layers, 1);
      stream_settings[i].num_temporal_layers = stream.num_temporal_layers;
    }
    if (stream.scale_resolution_down_by >= 1.0) {
      stream_settings[i].width = width / stream.scale_resolution_down_by;
      stream_settings[i].height = height / stream.scale_resolution_down_by;
    }
    stream_settings[i].scalability_mode = stream.scalability_mode;
    stream_settings[i].target_bitrate_bps = target_bitrate_bps;
    stream_settings[i].max_bitrate_bps = max_bitrate_bps;
    stream_settings[i].active =
        encoder_config.number_of_streams == 1 || stream.active;

    bitrate_left_bps -= stream_settings[i].target_bitrate_bps;
  }

  stream_settings[encoder_config.number_of_streams - 1].max_bitrate_bps +=
      bitrate_left_bps;
  stream_settings[0].bitrate_priority = encoder_config.bitrate_priority;

  return stream_settings;
}

DefaultVideoStreamFactory::DefaultVideoStreamFactory() {}

std::vector<VideoStream> DefaultVideoStreamFactory::CreateEncoderStreams(
    const FieldTrialsView& /*field_trials*/,
    int frame_width,
    int frame_height,
    const VideoEncoderConfig& encoder_config) {
  return CreateVideoStreams(frame_width, frame_height, encoder_config);
}

void FillEncoderConfiguration(VideoCodecType codec_type,
                              size_t num_streams,
                              VideoEncoderConfig* configuration) {
  RTC_DCHECK_LE(num_streams, DefaultVideoStreamFactory::kMaxNumberOfStreams);

  configuration->codec_type = codec_type;
  configuration->number_of_streams = num_streams;
  configuration->video_stream_factory =
      make_ref_counted<DefaultVideoStreamFactory>();
  configuration->max_bitrate_bps = 0;
  configuration->frame_drop_enabled = true;
  configuration->simulcast_layers = std::vector<VideoStream>(num_streams);
  for (size_t i = 0; i < num_streams; ++i) {
    configuration->max_bitrate_bps +=
        DefaultVideoStreamFactory::kMaxBitratePerStream[i];
  }
}

VideoReceiveStreamInterface::Decoder CreateMatchingDecoder(
    int payload_type,
    const std::string& payload_name) {
  VideoReceiveStreamInterface::Decoder decoder;
  decoder.payload_type = payload_type;
  decoder.video_format = SdpVideoFormat(payload_name);
  return decoder;
}

VideoReceiveStreamInterface::Decoder CreateMatchingDecoder(
    const VideoSendStream::Config& config) {
  return CreateMatchingDecoder(config.rtp.payload_type,
                               config.rtp.payload_name);
}

}  // namespace test
}  // namespace webrtc
