/*
 *  Copyright 2019 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/scenario/stats_collection.h"

#include "common_video/libyuv/include/webrtc_libyuv.h"
#include "rtc_base/memory_usage.h"
#include "rtc_base/thread.h"

namespace webrtc {
namespace test {

VideoQualityAnalyzer::VideoQualityAnalyzer(
    VideoQualityAnalyzerConfig config,
    std::unique_ptr<RtcEventLogOutput> writer)
    : config_(config), writer_(std::move(writer)) {
  if (writer_) {
    PrintHeaders();
  }
}

VideoQualityAnalyzer::~VideoQualityAnalyzer() = default;

void VideoQualityAnalyzer::PrintHeaders() {
  writer_->Write(
      "capture_time render_time capture_width capture_height render_width "
      "render_height psnr\n");
}

std::function<void(const VideoFramePair&)> VideoQualityAnalyzer::Handler() {
  return [this](VideoFramePair pair) { HandleFramePair(pair); };
}

void VideoQualityAnalyzer::HandleFramePair(VideoFramePair sample, double psnr) {
  layer_analyzers_[sample.layer_id].HandleFramePair(sample, psnr,
                                                    writer_.get());
  cached_.reset();
}

void VideoQualityAnalyzer::HandleFramePair(VideoFramePair sample) {
  double psnr = NAN;
  if (sample.decoded)
    psnr = I420PSNR(*sample.captured->ToI420(), *sample.decoded->ToI420());

  if (config_.thread) {
    config_.thread->PostTask(RTC_FROM_HERE, [this, sample, psnr] {
      HandleFramePair(std::move(sample), psnr);
    });
  } else {
    HandleFramePair(std::move(sample), psnr);
  }
}

std::vector<VideoQualityStats> VideoQualityAnalyzer::layer_stats() const {
  std::vector<VideoQualityStats> res;
  for (auto& layer : layer_analyzers_)
    res.push_back(layer.second.stats_);
  return res;
}

VideoQualityStats& VideoQualityAnalyzer::stats() {
  if (!cached_) {
    cached_ = VideoQualityStats();
    for (auto& layer : layer_analyzers_)
      cached_->AddStats(layer.second.stats_);
  }
  return *cached_;
}

void VideoLayerAnalyzer::HandleFramePair(VideoFramePair sample,
                                         double psnr,
                                         RtcEventLogOutput* writer) {
  RTC_CHECK(sample.captured);
  HandleCapturedFrame(sample);
  if (!sample.decoded) {
    // Can only happen in the beginning of a call or if the resolution is
    // reduced. Otherwise we will detect a freeze.
    ++stats_.lost_count;
    ++skip_count_;
  } else {
    stats_.psnr_with_freeze.AddSample(psnr);
    if (sample.repeated) {
      ++stats_.freeze_count;
      ++skip_count_;
    } else {
      stats_.psnr.AddSample(psnr);
      HandleRenderedFrame(sample);
    }
  }
  if (writer) {
    LogWriteFormat(writer, "%.3f %.3f %.3f %i %i %i %i %.3f\n",
                   sample.capture_time.seconds<double>(),
                   sample.render_time.seconds<double>(),
                   sample.captured->width(), sample.captured->height(),
                   sample.decoded->width(), sample.decoded->height(), psnr);
  }
}

void VideoLayerAnalyzer::HandleCapturedFrame(const VideoFramePair& sample) {
  stats_.capture.AddFrameInfo(*sample.captured, sample.capture_time);
  if (last_freeze_time_.IsInfinite())
    last_freeze_time_ = sample.capture_time;
}

void VideoLayerAnalyzer::HandleRenderedFrame(const VideoFramePair& sample) {
  stats_.capture_to_decoded_delay.AddSample(sample.decoded_time -
                                            sample.capture_time);
  stats_.end_to_end_delay.AddSample(sample.render_time - sample.capture_time);
  stats_.render.AddFrameInfo(*sample.decoded, sample.render_time);
  stats_.skipped_between_rendered.AddSample(skip_count_);
  skip_count_ = 0;

  if (last_render_time_.IsFinite()) {
    RTC_DCHECK(sample.render_time.IsFinite());
    TimeDelta render_interval = sample.render_time - last_render_time_;
    TimeDelta mean_interval = stats_.render.frames.interval().Mean();
    if (render_interval > TimeDelta::ms(150) + mean_interval ||
        render_interval > 3 * mean_interval) {
      stats_.freeze_duration.AddSample(render_interval);
      stats_.time_between_freezes.AddSample(last_render_time_ -
                                            last_freeze_time_);
      last_freeze_time_ = sample.render_time;
    }
  }
  last_render_time_ = sample.render_time;
}

void CallStatsCollector::AddStats(Call::Stats sample) {
  if (sample.send_bandwidth_bps > 0)
    stats_.target_rate.AddSampleBps(sample.send_bandwidth_bps);
  if (sample.pacer_delay_ms > 0)
    stats_.pacer_delay.AddSample(TimeDelta::ms(sample.pacer_delay_ms));
  if (sample.rtt_ms > 0)
    stats_.round_trip_time.AddSample(TimeDelta::ms(sample.rtt_ms));
  stats_.memory_usage.AddSample(rtc::GetProcessResidentSizeBytes());
}

void AudioReceiveStatsCollector::AddStats(AudioReceiveStream::Stats sample) {
  stats_.expand_rate.AddSample(sample.expand_rate);
  stats_.accelerate_rate.AddSample(sample.accelerate_rate);
  stats_.jitter_buffer.AddSampleMs(sample.jitter_buffer_ms);
}

void VideoSendStatsCollector::AddStats(VideoSendStream::Stats sample,
                                       Timestamp at_time) {
  // It's not certain that we yet have estimates for any of these stats.
  // Check that they are positive before mixing them in.
  if (sample.encode_frame_rate <= 0)
    return;

  stats_.encode_frame_rate.AddSample(sample.encode_frame_rate);
  stats_.encode_time.AddSampleMs(sample.avg_encode_time_ms);
  stats_.encode_usage.AddSample(sample.encode_usage_percent / 100.0);
  stats_.media_bitrate.AddSampleBps(sample.media_bitrate_bps);

  size_t fec_bytes = 0;
  for (const auto& kv : sample.substreams) {
    fec_bytes += kv.second.rtp_stats.fec.payload_bytes +
                 kv.second.rtp_stats.fec.padding_bytes;
  }
  if (last_update_.IsFinite()) {
    auto fec_delta = DataSize::bytes(fec_bytes - last_fec_bytes_);
    auto time_delta = at_time - last_update_;
    stats_.fec_bitrate.AddSample(fec_delta / time_delta);
  }
  last_fec_bytes_ = fec_bytes;
  last_update_ = at_time;
}

void VideoReceiveStatsCollector::AddStats(VideoReceiveStream::Stats sample) {
  if (sample.decode_ms > 0)
    stats_.decode_time.AddSampleMs(sample.decode_ms);
  if (sample.max_decode_ms > 0)
    stats_.decode_time_max.AddSampleMs(sample.max_decode_ms);
  if (sample.width > 0 && sample.height > 0) {
    stats_.decode_pixels.AddSample(sample.width * sample.height);
    stats_.resolution.AddSample(sample.height);
  }
}
}  // namespace test
}  // namespace webrtc
