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

#include <algorithm>
#include <string>

#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/strings/string_builder.h"
#include "system_wrappers/include/metrics.h"

namespace webrtc {

namespace {
const int kMinFrameSamplesToDetectFreeze = 5;
const int kMinCallDurationMs = 3000;
const int kMinRequiredSamples = 1;
const int kMinIncreaseForFreezeMs = 150;
const int kPixelsInHighResolution = 960 * 540;  // CPU-adapted HD still counts.
const int kPixelsInMediumResolution = 640 * 360;
const int kBlockyQpThresholdVp8 = 70;
const int kBlockyQpThresholdVp9 = 60;  // TODO(ilnik): tune this value.
// TODO(ilnik): Add H264/HEVC thresholds.
}  // namespace

VideoQualityObserver::VideoQualityObserver(VideoContentType content_type)
    : last_frame_decoded_ms_(-1),
      num_frames_decoded_(0),
      first_frame_decoded_ms_(-1),
      last_frame_pixels_(0),
      last_frame_qp_(0),
      last_unfreeze_time_(0),
      time_in_resolution_ms_(3, 0),
      current_resolution_(Resolution::Low),
      num_resolution_downgrades_(0),
      time_in_blocky_video_ms_(0),
      content_type_(content_type),
      is_paused_(false) {}

VideoQualityObserver::~VideoQualityObserver() {
  UpdateHistograms();
}

void VideoQualityObserver::UpdateHistograms() {
  // Don't report anything on an empty video stream.
  if (num_frames_decoded_ == 0) {
    return;
  }

  char log_stream_buf[2 * 1024];
  rtc::SimpleStringBuilder log_stream(log_stream_buf);

  if (last_frame_decoded_ms_ > last_unfreeze_time_) {
    smooth_playback_durations_.Add(last_frame_decoded_ms_ -
                                   last_unfreeze_time_);
  }

  std::string uma_prefix = videocontenttypehelpers::IsScreenshare(content_type_)
                               ? "WebRTC.Video.Screenshare"
                               : "WebRTC.Video";

  auto mean_time_between_freezes =
      smooth_playback_durations_.Avg(kMinRequiredSamples);
  if (mean_time_between_freezes) {
    RTC_HISTOGRAM_COUNTS_SPARSE_100000(uma_prefix + ".MeanTimeBetweenFreezesMs",
                                       *mean_time_between_freezes);
    log_stream << uma_prefix << ".MeanTimeBetweenFreezesMs "
               << *mean_time_between_freezes << "\n";
  }
  auto avg_freeze_length = freezes_durations_.Avg(kMinRequiredSamples);
  if (avg_freeze_length) {
    RTC_HISTOGRAM_COUNTS_SPARSE_100000(uma_prefix + ".MeanFreezeDurationMs",
                                       *avg_freeze_length);
    log_stream << uma_prefix << ".MeanFreezeDurationMs " << *avg_freeze_length
               << "\n";
  }

  int64_t call_duration_ms = last_frame_decoded_ms_ - first_frame_decoded_ms_;

  if (call_duration_ms >= kMinCallDurationMs) {
    int time_spent_in_hd_percentage = static_cast<int>(
        time_in_resolution_ms_[Resolution::High] * 100 / call_duration_ms);
    int time_with_blocky_video_percentage =
        static_cast<int>(time_in_blocky_video_ms_ * 100 / call_duration_ms);

    RTC_HISTOGRAM_COUNTS_SPARSE_100(uma_prefix + ".TimeInHdPercentage",
                                    time_spent_in_hd_percentage);
    log_stream << uma_prefix << ".TimeInHdPercentage "
               << time_spent_in_hd_percentage << "\n";
    RTC_HISTOGRAM_COUNTS_SPARSE_100(uma_prefix + ".TimeInBlockyVideoPercentage",
                                    time_with_blocky_video_percentage);
    log_stream << uma_prefix << ".TimeInBlockyVideoPercentage "
               << time_with_blocky_video_percentage << "\n";
    RTC_HISTOGRAM_COUNTS_SPARSE_100(
        uma_prefix + ".NumberResolutionDownswitchesPerMinute",
        num_resolution_downgrades_ * 60000 / call_duration_ms);
    log_stream << uma_prefix << ".NumberResolutionDownswitchesPerMinute "
               << num_resolution_downgrades_ * 60000 / call_duration_ms << "\n";
  }
  RTC_LOG(LS_INFO) << log_stream.str();
}

void VideoQualityObserver::OnDecodedFrame(rtc::Optional<uint8_t> qp,
                                          int width,
                                          int height,
                                          int64_t now_ms,
                                          VideoCodecType codec) {
  if (num_frames_decoded_ == 0) {
    first_frame_decoded_ms_ = now_ms;
    last_unfreeze_time_ = now_ms;
  }

  ++num_frames_decoded_;

  if (!is_paused_ && num_frames_decoded_ > 1) {
    // Process inter-frame delay.
    int64_t interframe_delay_ms = now_ms - last_frame_decoded_ms_;
    interframe_delays_.Add(interframe_delay_ms);
    rtc::Optional<int> avg_interframe_delay =
        interframe_delays_.Avg(kMinFrameSamplesToDetectFreeze);
    // Check if it was a freeze.
    if (avg_interframe_delay &&
        interframe_delay_ms >=
            std::max(3 * *avg_interframe_delay,
                     *avg_interframe_delay + kMinIncreaseForFreezeMs)) {
      freezes_durations_.Add(interframe_delay_ms);
      smooth_playback_durations_.Add(last_frame_decoded_ms_ -
                                     last_unfreeze_time_);
      last_unfreeze_time_ = now_ms;
    } else {
      // Only count inter-frame delay as playback time if there
      // was no freeze.
      time_in_resolution_ms_[current_resolution_] += interframe_delay_ms;
      rtc::Optional<int> qp_blocky_threshold;
      // TODO(ilnik): add other codec types when we have QP for them.
      switch (codec) {
        case kVideoCodecVP8:
          qp_blocky_threshold = kBlockyQpThresholdVp8;
          break;
        case kVideoCodecVP9:
          qp_blocky_threshold = kBlockyQpThresholdVp9;
          break;
        default:
          qp_blocky_threshold = rtc::nullopt;
      }
      if (qp_blocky_threshold && qp.value_or(0) > *qp_blocky_threshold) {
        time_in_blocky_video_ms_ += interframe_delay_ms;
      }
    }
  }

  if (is_paused_) {
    // If the stream was paused since the previous frame, do not count the
    // pause toward smooth playback. Explicitly count the part before it and
    // start the new smooth playback interval from this frame.
    is_paused_ = false;
    if (last_frame_decoded_ms_ > last_unfreeze_time_) {
      smooth_playback_durations_.Add(last_frame_decoded_ms_ -
                                     last_unfreeze_time_);
    }
    last_unfreeze_time_ = now_ms;
  }

  int64_t pixels = width * height;
  if (pixels >= kPixelsInHighResolution) {
    current_resolution_ = Resolution::High;
  } else if (pixels >= kPixelsInMediumResolution) {
    current_resolution_ = Resolution::Medium;
  } else {
    current_resolution_ = Resolution::Low;
  }

  if (pixels < last_frame_pixels_) {
    ++num_resolution_downgrades_;
  }

  last_frame_decoded_ms_ = now_ms;
  last_frame_qp_ = qp.value_or(0);
  last_frame_pixels_ = pixels;
}

void VideoQualityObserver::OnStreamInactive() {
  is_paused_ = true;
}
}  // namespace webrtc
