/*
 *  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 "modules/video_coding/codecs/vp9/svc_rate_allocator.h"

#include <algorithm>
#include <cmath>
#include <numeric>

#include "rtc_base/checks.h"

namespace webrtc {

namespace {
const float kSpatialLayeringRateScalingFactor = 0.55f;
const float kTemporalLayeringRateScalingFactor = 0.55f;
}  // namespace

SvcRateAllocator::SvcRateAllocator(const VideoCodec& codec) : codec_(codec) {
  RTC_DCHECK_EQ(codec.codecType, kVideoCodecVP9);
}

VideoBitrateAllocation SvcRateAllocator::GetAllocation(
    uint32_t total_bitrate_bps,
    uint32_t framerate_fps) {
  VideoBitrateAllocation bitrate_allocation;

  size_t num_spatial_layers = codec_.VP9().numberOfSpatialLayers;
  RTC_CHECK(num_spatial_layers > 0);
  size_t num_temporal_layers = codec_.VP9().numberOfTemporalLayers;
  RTC_CHECK(num_temporal_layers > 0);

  if (codec_.maxBitrate != 0) {
    total_bitrate_bps = std::min(total_bitrate_bps, codec_.maxBitrate * 1000);
  }

  if (codec_.mode == kScreensharing) {
    // At screen sharing bitrate allocation is handled by VP9 encoder wrapper.
    bitrate_allocation.SetBitrate(0, 0, total_bitrate_bps);
    return bitrate_allocation;
  }

  std::vector<size_t> spatial_layer_bitrate_bps;

  if (codec_.spatialLayers[0].maxBitrate == 0) {
    // Layers' parameters are not initialized. Do simple split.
    spatial_layer_bitrate_bps =
        SplitBitrate(num_spatial_layers, total_bitrate_bps,
                     kSpatialLayeringRateScalingFactor);
  } else {
    // Distribute total bitrate across spatial layers. If there is not enough
    // bitrate to provide all layers with at least minimum required bitrate
    // then number of layers is reduced by one and distribution is repeated
    // until that condition is met or if number of layers is reduced to one.
    for (;; --num_spatial_layers) {
      spatial_layer_bitrate_bps =
          SplitBitrate(num_spatial_layers, total_bitrate_bps,
                       kSpatialLayeringRateScalingFactor);

      bool enough_bitrate = true;
      size_t excess_rate = 0;
      for (size_t sl_idx = 0; sl_idx < num_spatial_layers; ++sl_idx) {
        RTC_DCHECK_GT(codec_.spatialLayers[sl_idx].maxBitrate, 0);
        RTC_DCHECK_GE(codec_.spatialLayers[sl_idx].maxBitrate,
                      codec_.spatialLayers[sl_idx].minBitrate);

        const size_t min_bitrate_bps =
            codec_.spatialLayers[sl_idx].minBitrate * 1000;
        const size_t max_bitrate_bps =
            codec_.spatialLayers[sl_idx].maxBitrate * 1000;

        spatial_layer_bitrate_bps[sl_idx] += excess_rate;
        if (spatial_layer_bitrate_bps[sl_idx] < max_bitrate_bps) {
          excess_rate = 0;
        } else {
          excess_rate = spatial_layer_bitrate_bps[sl_idx] - max_bitrate_bps;
          spatial_layer_bitrate_bps[sl_idx] = max_bitrate_bps;
        }

        if (spatial_layer_bitrate_bps[sl_idx] < min_bitrate_bps) {
          enough_bitrate = false;
          break;
        }
      }

      if (enough_bitrate || num_spatial_layers == 1) {
        break;
      }
    }
  }

  for (size_t sl_idx = 0; sl_idx < num_spatial_layers; ++sl_idx) {
    std::vector<size_t> temporal_layer_bitrate_bps =
        SplitBitrate(num_temporal_layers, spatial_layer_bitrate_bps[sl_idx],
                     kTemporalLayeringRateScalingFactor);

    // Distribute rate across temporal layers. Allocate more bits to lower
    // layers since they are used for prediction of higher layers and their
    // references are far apart.
    if (num_temporal_layers == 1) {
      bitrate_allocation.SetBitrate(sl_idx, 0, temporal_layer_bitrate_bps[0]);
    } else if (num_temporal_layers == 2) {
      bitrate_allocation.SetBitrate(sl_idx, 0, temporal_layer_bitrate_bps[1]);
      bitrate_allocation.SetBitrate(sl_idx, 1, temporal_layer_bitrate_bps[0]);
    } else {
      RTC_CHECK_EQ(num_temporal_layers, 3);
      // In case of three temporal layers the high layer has two frames and the
      // middle layer has one frame within GOP (in between two consecutive low
      // layer frames). Thus high layer requires more bits (comparing pure
      // bitrate of layer, excluding bitrate of base layers) to keep quality on
      // par with lower layers.
      bitrate_allocation.SetBitrate(sl_idx, 0, temporal_layer_bitrate_bps[2]);
      bitrate_allocation.SetBitrate(sl_idx, 1, temporal_layer_bitrate_bps[0]);
      bitrate_allocation.SetBitrate(sl_idx, 2, temporal_layer_bitrate_bps[1]);
    }
  }

  return bitrate_allocation;
}

uint32_t SvcRateAllocator::GetPreferredBitrateBps(uint32_t framerate) {
  return GetAllocation(codec_.maxBitrate * 1000, framerate).get_sum_bps();
}

std::vector<size_t> SvcRateAllocator::SplitBitrate(size_t num_layers,
                                                   size_t total_bitrate,
                                                   float rate_scaling_factor) {
  std::vector<size_t> bitrates;

  double denominator = 0.0;
  for (size_t layer_idx = 0; layer_idx < num_layers; ++layer_idx) {
    denominator += std::pow(rate_scaling_factor, layer_idx);
  }

  double numerator = std::pow(rate_scaling_factor, num_layers - 1);
  for (size_t layer_idx = 0; layer_idx < num_layers; ++layer_idx) {
    bitrates.push_back(numerator * total_bitrate / denominator);
    numerator /= rate_scaling_factor;
  }

  const size_t sum = std::accumulate(bitrates.begin(), bitrates.end(), 0);
  // Ensure the sum of split bitrates doesn't exceed the total bitrate.
  RTC_DCHECK_LE(sum, total_bitrate);

  // Keep the sum of split bitrates equal to the total bitrate by adding bits,
  // which were lost due to rounding, to the latest layer.
  bitrates.back() += total_bitrate - sum;

  return bitrates;
}

}  // namespace webrtc
