/*
 *  Copyright 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 "test/scenario/quality_stats.h"

#include <utility>

#include "common_video/libyuv/include/webrtc_libyuv.h"
#include "rtc_base/checks.h"
#include "rtc_base/event.h"

namespace webrtc {
namespace test {

VideoQualityAnalyzer::VideoQualityAnalyzer(
    std::string filename_or_empty,
    std::function<void(const VideoFrameQualityInfo&)> frame_info_handler)
    : task_queue_("VideoAnalyzer") {
  if (!filename_or_empty.empty()) {
    output_file_ = fopen(filename_or_empty.c_str(), "w");
    RTC_CHECK(output_file_);
    PrintHeaders();
    frame_info_handlers_.push_back(
        [this](const VideoFrameQualityInfo& info) { PrintFrameInfo(info); });
  }
  if (frame_info_handler)
    frame_info_handlers_.push_back(frame_info_handler);
}

VideoQualityAnalyzer::~VideoQualityAnalyzer() {
  rtc::Event event;
  task_queue_.PostTask([&event] { event.Set(); });
  event.Wait(rtc::Event::kForever);
  if (output_file_)
    fclose(output_file_);
}

void VideoQualityAnalyzer::OnCapturedFrame(const VideoFrame& frame) {
  VideoFrame copy = frame;
  task_queue_.PostTask([this, copy] {
    if (!first_capture_ntp_time_ms_)
      first_capture_ntp_time_ms_ = copy.ntp_time_ms();
    captured_frames_.push_back(std::move(copy));
  });
}

void VideoQualityAnalyzer::OnDecodedFrame(const VideoFrame& frame) {
  VideoFrame decoded = frame;
  RTC_CHECK(frame.ntp_time_ms());
  RTC_CHECK(frame.timestamp());
  task_queue_.PostTask([this, decoded] {
    // If first frame never is received, this value will be wrong. However, that
    // is something that is very unlikely to happen.
    if (!first_decode_rtp_timestamp_)
      first_decode_rtp_timestamp_ = decoded.timestamp();
    RTC_CHECK(!captured_frames_.empty());
    int64_t decoded_capture_time_ms = DecodedFrameCaptureTimeOffsetMs(decoded);
    while (CapturedFrameCaptureTimeOffsetMs(captured_frames_.front()) <
           decoded_capture_time_ms) {
      VideoFrame lost = std::move(captured_frames_.front());
      captured_frames_.pop_front();
      VideoFrameQualityInfo lost_info =
          VideoFrameQualityInfo{Timestamp::us(lost.timestamp_us()),
                                Timestamp::PlusInfinity(),
                                Timestamp::PlusInfinity(),
                                lost.width(),
                                lost.height(),
                                NAN};
      for (auto& handler : frame_info_handlers_)
        handler(lost_info);
      RTC_CHECK(!captured_frames_.empty());
    }
    RTC_CHECK(!captured_frames_.empty());
    RTC_CHECK(CapturedFrameCaptureTimeOffsetMs(captured_frames_.front()) ==
              DecodedFrameCaptureTimeOffsetMs(decoded));
    VideoFrame captured = std::move(captured_frames_.front());
    captured_frames_.pop_front();

    VideoFrameQualityInfo decoded_info =
        VideoFrameQualityInfo{Timestamp::us(captured.timestamp_us()),
                              Timestamp::ms(decoded.timestamp() / 90.0),
                              Timestamp::ms(decoded.render_time_ms()),
                              decoded.width(),
                              decoded.height(),
                              I420PSNR(&captured, &decoded)};
    for (auto& handler : frame_info_handlers_)
      handler(decoded_info);
  });
}

bool VideoQualityAnalyzer::Active() const {
  return !frame_info_handlers_.empty();
}

int64_t VideoQualityAnalyzer::DecodedFrameCaptureTimeOffsetMs(
    const VideoFrame& decoded) const {
  // Assumes that the underlying resolution is ms.
  // Note that we intentinally allow wraparound. The code is incorrect for
  // durations of more than UINT32_MAX/90 ms.
  RTC_DCHECK(first_decode_rtp_timestamp_);
  return (decoded.timestamp() - *first_decode_rtp_timestamp_) / 90;
}

int64_t VideoQualityAnalyzer::CapturedFrameCaptureTimeOffsetMs(
    const VideoFrame& captured) const {
  RTC_DCHECK(first_capture_ntp_time_ms_);
  return captured.ntp_time_ms() - *first_capture_ntp_time_ms_;
}

void VideoQualityAnalyzer::PrintHeaders() {
  fprintf(output_file_, "capt recv_capt render width height psnr\n");
}

void VideoQualityAnalyzer::PrintFrameInfo(const VideoFrameQualityInfo& sample) {
  fprintf(output_file_, "%.3f %.3f %.3f %i %i %.3f\n",
          sample.capture_time.seconds<double>(),
          sample.received_capture_time.seconds<double>(),
          sample.render_time.seconds<double>(), sample.width, sample.height,
          sample.psnr);
}

void VideoQualityStats::HandleFrameInfo(VideoFrameQualityInfo sample) {
  total++;
  if (sample.render_time.IsInfinite()) {
    ++lost;
  } else {
    ++valid;
    end_to_end_seconds.AddSample(
        (sample.render_time - sample.capture_time).seconds<double>());
    psnr.AddSample(sample.psnr);
  }
}

ForwardingCapturedFrameTap::ForwardingCapturedFrameTap(
    const Clock* clock,
    VideoQualityAnalyzer* analyzer,
    rtc::VideoSourceInterface<VideoFrame>* source)
    : clock_(clock), analyzer_(analyzer), source_(source) {}

ForwardingCapturedFrameTap::~ForwardingCapturedFrameTap() {}

void ForwardingCapturedFrameTap::OnFrame(const VideoFrame& frame) {
  RTC_CHECK(sink_);
  VideoFrame copy = frame;
  if (frame.ntp_time_ms() == 0)
    copy.set_ntp_time_ms(clock_->CurrentNtpInMilliseconds());
  copy.set_timestamp(copy.ntp_time_ms() * 90);
  analyzer_->OnCapturedFrame(copy);
  sink_->OnFrame(copy);
}
void ForwardingCapturedFrameTap::OnDiscardedFrame() {
  RTC_CHECK(sink_);
  discarded_count_++;
  sink_->OnDiscardedFrame();
}

void ForwardingCapturedFrameTap::AddOrUpdateSink(
    VideoSinkInterface<VideoFrame>* sink,
    const rtc::VideoSinkWants& wants) {
  sink_ = sink;
  source_->AddOrUpdateSink(this, wants);
}
void ForwardingCapturedFrameTap::RemoveSink(
    VideoSinkInterface<VideoFrame>* sink) {
  source_->RemoveSink(this);
  sink_ = nullptr;
}

DecodedFrameTap::DecodedFrameTap(VideoQualityAnalyzer* analyzer)
    : analyzer_(analyzer) {}

void DecodedFrameTap::OnFrame(const VideoFrame& frame) {
  analyzer_->OnDecodedFrame(frame);
}

}  // namespace test
}  // namespace webrtc
