/*
 *  Copyright (c) 2013 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 "webrtc/modules/audio_coding/neteq/decision_logic.h"

#include <algorithm>

#include "webrtc/modules/audio_coding/neteq/buffer_level_filter.h"
#include "webrtc/modules/audio_coding/neteq/decision_logic_fax.h"
#include "webrtc/modules/audio_coding/neteq/decision_logic_normal.h"
#include "webrtc/modules/audio_coding/neteq/delay_manager.h"
#include "webrtc/modules/audio_coding/neteq/expand.h"
#include "webrtc/modules/audio_coding/neteq/packet_buffer.h"
#include "webrtc/modules/audio_coding/neteq/sync_buffer.h"
#include "webrtc/system_wrappers/interface/logging.h"

namespace webrtc {

DecisionLogic* DecisionLogic::Create(int fs_hz,
                                     int output_size_samples,
                                     NetEqPlayoutMode playout_mode,
                                     DecoderDatabase* decoder_database,
                                     const PacketBuffer& packet_buffer,
                                     DelayManager* delay_manager,
                                     BufferLevelFilter* buffer_level_filter) {
  switch (playout_mode) {
    case kPlayoutOn:
    case kPlayoutStreaming:
      return new DecisionLogicNormal(fs_hz,
                                     output_size_samples,
                                     playout_mode,
                                     decoder_database,
                                     packet_buffer,
                                     delay_manager,
                                     buffer_level_filter);
    case kPlayoutFax:
    case kPlayoutOff:
      return new DecisionLogicFax(fs_hz,
                                  output_size_samples,
                                  playout_mode,
                                  decoder_database,
                                  packet_buffer,
                                  delay_manager,
                                  buffer_level_filter);
  }
  // This line cannot be reached, but must be here to avoid compiler errors.
  assert(false);
  return NULL;
}

DecisionLogic::DecisionLogic(int fs_hz,
                             int output_size_samples,
                             NetEqPlayoutMode playout_mode,
                             DecoderDatabase* decoder_database,
                             const PacketBuffer& packet_buffer,
                             DelayManager* delay_manager,
                             BufferLevelFilter* buffer_level_filter)
    : decoder_database_(decoder_database),
      packet_buffer_(packet_buffer),
      delay_manager_(delay_manager),
      buffer_level_filter_(buffer_level_filter),
      cng_state_(kCngOff),
      generated_noise_samples_(0),
      packet_length_samples_(0),
      sample_memory_(0),
      prev_time_scale_(false),
      timescale_hold_off_(kMinTimescaleInterval),
      num_consecutive_expands_(0),
      playout_mode_(playout_mode) {
  delay_manager_->set_streaming_mode(playout_mode_ == kPlayoutStreaming);
  SetSampleRate(fs_hz, output_size_samples);
}

void DecisionLogic::Reset() {
  cng_state_ = kCngOff;
  generated_noise_samples_ = 0;
  packet_length_samples_ = 0;
  sample_memory_ = 0;
  prev_time_scale_ = false;
  timescale_hold_off_ = 0;
  num_consecutive_expands_ = 0;
}

void DecisionLogic::SoftReset() {
  packet_length_samples_ = 0;
  sample_memory_ = 0;
  prev_time_scale_ = false;
  timescale_hold_off_ = kMinTimescaleInterval;
}

void DecisionLogic::SetSampleRate(int fs_hz, int output_size_samples) {
  // TODO(hlundin): Change to an enumerator and skip assert.
  assert(fs_hz == 8000 || fs_hz == 16000 || fs_hz ==  32000 || fs_hz == 48000);
  fs_mult_ = fs_hz / 8000;
  output_size_samples_ = output_size_samples;
}

Operations DecisionLogic::GetDecision(const SyncBuffer& sync_buffer,
                                      const Expand& expand,
                                      int decoder_frame_length,
                                      const RTPHeader* packet_header,
                                      Modes prev_mode,
                                      bool play_dtmf, bool* reset_decoder) {
  if (prev_mode == kModeRfc3389Cng ||
      prev_mode == kModeCodecInternalCng ||
      prev_mode == kModeExpand) {
    // If last mode was CNG (or Expand, since this could be covering up for
    // a lost CNG packet), increase the |generated_noise_samples_| counter.
    generated_noise_samples_ += output_size_samples_;
    // Remember that CNG is on. This is needed if comfort noise is interrupted
    // by DTMF.
    if (prev_mode == kModeRfc3389Cng) {
      cng_state_ = kCngRfc3389On;
    } else if (prev_mode == kModeCodecInternalCng) {
      cng_state_ = kCngInternalOn;
    }
  }

  const int samples_left = static_cast<int>(
      sync_buffer.FutureLength() - expand.overlap_length());
  const int cur_size_samples =
      samples_left + packet_buffer_.NumSamplesInBuffer(decoder_database_,
                                                       decoder_frame_length);
  LOG(LS_VERBOSE) << "Buffers: " << packet_buffer_.NumPacketsInBuffer() <<
      " packets * " << decoder_frame_length << " samples/packet + " <<
      samples_left << " samples in sync buffer = " << cur_size_samples;

  prev_time_scale_ = prev_time_scale_ &&
      (prev_mode == kModeAccelerateSuccess ||
          prev_mode == kModeAccelerateLowEnergy ||
          prev_mode == kModePreemptiveExpandSuccess ||
          prev_mode == kModePreemptiveExpandLowEnergy);

  FilterBufferLevel(cur_size_samples, prev_mode);

  return GetDecisionSpecialized(sync_buffer, expand, decoder_frame_length,
                                packet_header, prev_mode, play_dtmf,
                                reset_decoder);
}

void DecisionLogic::ExpandDecision(Operations operation) {
  if (operation == kExpand) {
    num_consecutive_expands_++;
  } else {
    num_consecutive_expands_ = 0;
  }
}

void DecisionLogic::FilterBufferLevel(int buffer_size_samples,
                                      Modes prev_mode) {
  const int elapsed_time_ms = output_size_samples_ / (8 * fs_mult_);
  delay_manager_->UpdateCounters(elapsed_time_ms);

  // Do not update buffer history if currently playing CNG since it will bias
  // the filtered buffer level.
  if ((prev_mode != kModeRfc3389Cng) && (prev_mode != kModeCodecInternalCng)) {
    buffer_level_filter_->SetTargetBufferLevel(
        delay_manager_->base_target_level());

    int buffer_size_packets = 0;
    if (packet_length_samples_ > 0) {
      // Calculate size in packets.
      buffer_size_packets = buffer_size_samples / packet_length_samples_;
    }
    int sample_memory_local = 0;
    if (prev_time_scale_) {
      sample_memory_local = sample_memory_;
      timescale_hold_off_ = kMinTimescaleInterval;
    }
    buffer_level_filter_->Update(buffer_size_packets, sample_memory_local,
                                 packet_length_samples_);
    prev_time_scale_ = false;
  }

  timescale_hold_off_ = std::max(timescale_hold_off_ - 1, 0);
}

}  // namespace webrtc
