/*
 *  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/video/send_statistics_proxy.h"

#include <map>

#include "webrtc/base/checks.h"

#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/logging.h"

namespace webrtc {

const int SendStatisticsProxy::kStatsTimeoutMs = 5000;

SendStatisticsProxy::SendStatisticsProxy(Clock* clock,
                                         const VideoSendStream::Config& config)
    : clock_(clock),
      config_(config),
      crit_(CriticalSectionWrapper::CreateCriticalSection()) {
}

SendStatisticsProxy::~SendStatisticsProxy() {}

void SendStatisticsProxy::OutgoingRate(const int video_channel,
                                       const unsigned int framerate,
                                       const unsigned int bitrate) {
  CriticalSectionScoped lock(crit_.get());
  stats_.encode_frame_rate = framerate;
  stats_.media_bitrate_bps = bitrate;
}

void SendStatisticsProxy::CpuOveruseMetricsUpdated(
    const CpuOveruseMetrics& metrics) {
  CriticalSectionScoped lock(crit_.get());
  stats_.avg_encode_time_ms = metrics.avg_encode_time_ms;
  stats_.encode_usage_percent = metrics.encode_usage_percent;
}

void SendStatisticsProxy::SuspendChange(int video_channel, bool is_suspended) {
  CriticalSectionScoped lock(crit_.get());
  stats_.suspended = is_suspended;
}

void SendStatisticsProxy::CapturedFrameRate(const int capture_id,
                                            const unsigned char frame_rate) {
  CriticalSectionScoped lock(crit_.get());
  stats_.input_frame_rate = frame_rate;
}

VideoSendStream::Stats SendStatisticsProxy::GetStats() {
  CriticalSectionScoped lock(crit_.get());
  PurgeOldStats();
  return stats_;
}

void SendStatisticsProxy::PurgeOldStats() {
  int64_t current_time_ms = clock_->TimeInMilliseconds();
  for (std::map<uint32_t, VideoSendStream::StreamStats>::iterator it =
           stats_.substreams.begin();
       it != stats_.substreams.end(); ++it) {
    uint32_t ssrc = it->first;
    if (update_times_[ssrc].resolution_update_ms + kStatsTimeoutMs >
        current_time_ms)
      continue;

    it->second.width = 0;
    it->second.height = 0;
  }
}

VideoSendStream::StreamStats* SendStatisticsProxy::GetStatsEntry(
    uint32_t ssrc) {
  std::map<uint32_t, VideoSendStream::StreamStats>::iterator it =
      stats_.substreams.find(ssrc);
  if (it != stats_.substreams.end())
    return &it->second;

  if (std::find(config_.rtp.ssrcs.begin(), config_.rtp.ssrcs.end(), ssrc) ==
          config_.rtp.ssrcs.end() &&
      std::find(config_.rtp.rtx.ssrcs.begin(),
                config_.rtp.rtx.ssrcs.end(),
                ssrc) == config_.rtp.rtx.ssrcs.end()) {
    return NULL;
  }

  return &stats_.substreams[ssrc];  // Insert new entry and return ptr.
}

void SendStatisticsProxy::OnSetRates(uint32_t bitrate_bps, int framerate) {
  CriticalSectionScoped lock(crit_.get());
  stats_.target_media_bitrate_bps = bitrate_bps;
}

void SendStatisticsProxy::OnSendEncodedImage(
    const EncodedImage& encoded_image,
    const RTPVideoHeader* rtp_video_header) {
  size_t simulcast_idx =
      rtp_video_header != NULL ? rtp_video_header->simulcastIdx : 0;
  if (simulcast_idx >= config_.rtp.ssrcs.size()) {
    LOG(LS_ERROR) << "Encoded image outside simulcast range (" << simulcast_idx
                  << " >= " << config_.rtp.ssrcs.size() << ").";
    return;
  }
  uint32_t ssrc = config_.rtp.ssrcs[simulcast_idx];

  CriticalSectionScoped lock(crit_.get());
  VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
  if (stats == NULL)
    return;

  stats->width = encoded_image._encodedWidth;
  stats->height = encoded_image._encodedHeight;
  update_times_[ssrc].resolution_update_ms = clock_->TimeInMilliseconds();
}

void SendStatisticsProxy::RtcpPacketTypesCounterUpdated(
    uint32_t ssrc,
    const RtcpPacketTypeCounter& packet_counter) {
  CriticalSectionScoped lock(crit_.get());
  VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
  if (stats == NULL)
    return;

  stats->rtcp_packet_type_counts = packet_counter;
}

void SendStatisticsProxy::StatisticsUpdated(const RtcpStatistics& statistics,
                                            uint32_t ssrc) {
  CriticalSectionScoped lock(crit_.get());
  VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
  if (stats == NULL)
    return;

  stats->rtcp_stats = statistics;
}

void SendStatisticsProxy::CNameChanged(const char* cname, uint32_t ssrc) {
}

void SendStatisticsProxy::DataCountersUpdated(
    const StreamDataCounters& counters,
    uint32_t ssrc) {
  CriticalSectionScoped lock(crit_.get());
  VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
  DCHECK(stats != NULL) << "DataCountersUpdated reported for unknown ssrc: "
                        << ssrc;

  stats->rtp_stats = counters;
}

void SendStatisticsProxy::Notify(const BitrateStatistics& total_stats,
                                 const BitrateStatistics& retransmit_stats,
                                 uint32_t ssrc) {
  CriticalSectionScoped lock(crit_.get());
  VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
  if (stats == NULL)
    return;

  stats->total_bitrate_bps = total_stats.bitrate_bps;
  stats->retransmit_bitrate_bps = retransmit_stats.bitrate_bps;
}

void SendStatisticsProxy::FrameCountUpdated(const FrameCounts& frame_counts,
                                            uint32_t ssrc) {
  CriticalSectionScoped lock(crit_.get());
  VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
  if (stats == NULL)
    return;

  stats->frame_counts = frame_counts;
}

void SendStatisticsProxy::SendSideDelayUpdated(int avg_delay_ms,
                                               int max_delay_ms,
                                               uint32_t ssrc) {
  CriticalSectionScoped lock(crit_.get());
  VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
  if (stats == NULL)
    return;
  stats->avg_delay_ms = avg_delay_ms;
  stats->max_delay_ms = max_delay_ms;
}

}  // namespace webrtc
