/*
 *  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::unique_ptr<RtcEventLogOutput> writer,
    std::function<void(const VideoFrameQualityInfo&)> frame_info_handler)
    : writer_(std::move(writer)), task_queue_("VideoAnalyzer") {
  if (writer_) {
    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() {
  task_queue_.SendTask([] {});
}

void VideoQualityAnalyzer::OnCapturedFrame(const VideoFrame& frame) {
  VideoFrame copy = frame;
  task_queue_.PostTask([this, copy]() mutable {
    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] {
    // TODO(srte): Add detection and handling of lost frames.
    RTC_CHECK(!captured_frames_.empty());
    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();
}

void VideoQualityAnalyzer::PrintHeaders() {
  writer_->Write("capt recv_capt render width height psnr\n");
}

void VideoQualityAnalyzer::PrintFrameInfo(const VideoFrameQualityInfo& sample) {
  LogWriteFormat(writer_.get(), "%.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(
    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
