/*
 *  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 "api/scoped_refptr.h"
#include "api/video_codecs/sdp_video_format.h"
#include "call/rtp_config.h"
#include "rtc_base/checks.h"
#include "rtc_base/ref_counted_object.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 webrtc::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
            : DefaultVideoStreamFactory::kMaxBitratePerStream[i];
    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].target_bitrate_bps = target_bitrate_bps;
    stream_settings[i].max_bitrate_bps = max_bitrate_bps;
    stream_settings[i].active = 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(
    int width,
    int height,
    const webrtc::VideoEncoderConfig& encoder_config) {
  return CreateVideoStreams(width, 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 =
      new rtc::RefCountedObject<DefaultVideoStreamFactory>();
  configuration->max_bitrate_bps = 0;
  configuration->simulcast_layers = std::vector<VideoStream>(num_streams);
  for (size_t i = 0; i < num_streams; ++i) {
    configuration->max_bitrate_bps +=
        DefaultVideoStreamFactory::kMaxBitratePerStream[i];
  }
}

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

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

}  // namespace test
}  // namespace webrtc
