/*
 *  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 "webrtc/video_engine/vie_channel_group.h"

#include "webrtc/common.h"
#include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
#include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
#include "webrtc/modules/utility/interface/process_thread.h"
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/video_engine/call_stats.h"
#include "webrtc/video_engine/encoder_state_feedback.h"
#include "webrtc/video_engine/vie_channel.h"
#include "webrtc/video_engine/vie_encoder.h"
#include "webrtc/video_engine/vie_remb.h"

namespace webrtc {
namespace {

class WrappingBitrateEstimator : public RemoteBitrateEstimator {
 public:
  WrappingBitrateEstimator(RemoteBitrateObserver* observer, Clock* clock,
                           ProcessThread* process_thread)
      : observer_(observer),
        clock_(clock),
        process_thread_(process_thread),
        crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
        rbe_(RemoteBitrateEstimatorFactory().Create(observer_, clock_)),
        receive_absolute_send_time_(false) {
    assert(process_thread_ != NULL);
    process_thread_->RegisterModule(rbe_.get());
  }
  virtual ~WrappingBitrateEstimator() {
    process_thread_->DeRegisterModule(rbe_.get());
  }

  void SetReceiveAbsoluteSendTimeStatus(bool enable) {
    CriticalSectionScoped cs(crit_sect_.get());
    if (enable == receive_absolute_send_time_) {
      return;
    }

    process_thread_->DeRegisterModule(rbe_.get());
    if (enable) {
      rbe_.reset(AbsoluteSendTimeRemoteBitrateEstimatorFactory().Create(
          observer_, clock_));
    } else {
      rbe_.reset(RemoteBitrateEstimatorFactory().Create(observer_, clock_));
    }
    process_thread_->RegisterModule(rbe_.get());

    receive_absolute_send_time_ = enable;
  }

  virtual void IncomingPacket(int64_t arrival_time_ms,
                              int payload_size,
                              const RTPHeader& header) {
    CriticalSectionScoped cs(crit_sect_.get());
    rbe_->IncomingPacket(arrival_time_ms, payload_size, header);
  }

  virtual int32_t Process() {
    assert(false && "Not supposed to register the WrappingBitrateEstimator!");
    return 0;
  }

  virtual int32_t TimeUntilNextProcess() {
    assert(false && "Not supposed to register the WrappingBitrateEstimator!");
    return 0;
  }

  virtual void OnRttUpdate(uint32_t rtt) {
    CriticalSectionScoped cs(crit_sect_.get());
    rbe_->OnRttUpdate(rtt);
  }

  virtual void RemoveStream(unsigned int ssrc) {
    CriticalSectionScoped cs(crit_sect_.get());
    rbe_->RemoveStream(ssrc);
  }

  virtual bool LatestEstimate(std::vector<unsigned int>* ssrcs,
                              unsigned int* bitrate_bps) const {
    CriticalSectionScoped cs(crit_sect_.get());
    return rbe_->LatestEstimate(ssrcs, bitrate_bps);
  }

 private:
  RemoteBitrateObserver* observer_;
  Clock* clock_;
  ProcessThread* process_thread_;
  scoped_ptr<CriticalSectionWrapper> crit_sect_;
  scoped_ptr<RemoteBitrateEstimator> rbe_;
  bool receive_absolute_send_time_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(WrappingBitrateEstimator);
};
}  // namespace

ChannelGroup::ChannelGroup(ProcessThread* process_thread,
                           const Config& config)
    : remb_(new VieRemb()),
      bitrate_controller_(BitrateController::CreateBitrateController()),
      call_stats_(new CallStats()),
      remote_bitrate_estimator_(new WrappingBitrateEstimator(remb_.get(),
                                Clock::GetRealTimeClock(), process_thread)),
      encoder_state_feedback_(new EncoderStateFeedback()),
      process_thread_(process_thread) {
  call_stats_->RegisterStatsObserver(remote_bitrate_estimator_.get());
  process_thread->RegisterModule(call_stats_.get());
}

ChannelGroup::~ChannelGroup() {
  call_stats_->DeregisterStatsObserver(remote_bitrate_estimator_.get());
  process_thread_->DeRegisterModule(call_stats_.get());
  assert(channels_.empty());
  assert(!remb_->InUse());
}

void ChannelGroup::AddChannel(int channel_id) {
  channels_.insert(channel_id);
}

void ChannelGroup::RemoveChannel(int channel_id, unsigned int ssrc) {
  channels_.erase(channel_id);
  remote_bitrate_estimator_->RemoveStream(ssrc);
}

bool ChannelGroup::HasChannel(int channel_id) {
  return channels_.find(channel_id) != channels_.end();
}

bool ChannelGroup::Empty() {
  return channels_.empty();
}

BitrateController* ChannelGroup::GetBitrateController() {
  return bitrate_controller_.get();
}

RemoteBitrateEstimator* ChannelGroup::GetRemoteBitrateEstimator() {
  return remote_bitrate_estimator_.get();
}

CallStats* ChannelGroup::GetCallStats() {
  return call_stats_.get();
}

EncoderStateFeedback* ChannelGroup::GetEncoderStateFeedback() {
  return encoder_state_feedback_.get();
}

bool ChannelGroup::SetChannelRembStatus(int channel_id, bool sender,
                                        bool receiver, ViEChannel* channel) {
  // Update the channel state.
  if (sender || receiver) {
    if (!channel->EnableRemb(true)) {
      return false;
    }
  } else {
    channel->EnableRemb(false);
  }
  // Update the REMB instance with necessary RTP modules.
  RtpRtcp* rtp_module = channel->rtp_rtcp();
  if (sender) {
    remb_->AddRembSender(rtp_module);
  } else {
    remb_->RemoveRembSender(rtp_module);
  }
  if (receiver) {
    remb_->AddReceiveChannel(rtp_module);
  } else {
    remb_->RemoveReceiveChannel(rtp_module);
  }
  return true;
}

void ChannelGroup::SetReceiveAbsoluteSendTimeStatus(bool enable) {
  static_cast<WrappingBitrateEstimator*>(remote_bitrate_estimator_.get())->
      SetReceiveAbsoluteSendTimeStatus(enable);
}
}  // namespace webrtc
