// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "cast/standalone_sender/looping_file_sender.h"

#include "util/trace_logging.h"

namespace openscreen {
namespace cast {

LoopingFileSender::LoopingFileSender(Environment* environment,
                                     const char* path,
                                     SenderSession::ConfiguredSenders senders,
                                     int max_bitrate)
    : env_(environment),
      path_(path),
      packet_router_(env_),
      max_bitrate_(max_bitrate),
      audio_encoder_(senders.audio_sender->config().channels,
                     StreamingOpusEncoder::kDefaultCastAudioFramesPerSecond,
                     senders.audio_sender),
      video_encoder_(StreamingVp8Encoder::Parameters{},
                     env_->task_runner(),
                     senders.video_sender),
      next_task_(env_->now_function(), env_->task_runner()),
      console_update_task_(env_->now_function(), env_->task_runner()) {
  // Opus and Vp8 are the default values for the config, and if these are set
  // to a different value that means we offered a codec that we do not
  // support, which is a developer error.
  OSP_CHECK(senders.audio_config.codec == AudioCodec::kOpus);
  OSP_CHECK(senders.video_config.codec == VideoCodec::kVp8);
  OSP_LOG_INFO << "Max allowed media bitrate (audio + video) will be "
               << max_bitrate_;
  bandwidth_being_utilized_ = max_bitrate_ / 2;
  UpdateEncoderBitrates();

  next_task_.Schedule([this] { SendFileAgain(); }, Alarm::kImmediately);
}

LoopingFileSender::~LoopingFileSender() = default;

void LoopingFileSender::UpdateEncoderBitrates() {
  if (bandwidth_being_utilized_ >= kHighBandwidthThreshold) {
    audio_encoder_.UseHighQuality();
  } else {
    audio_encoder_.UseStandardQuality();
  }
  video_encoder_.SetTargetBitrate(bandwidth_being_utilized_ -
                                  audio_encoder_.GetBitrate());
}

void LoopingFileSender::ControlForNetworkCongestion() {
  bandwidth_estimate_ = packet_router_.ComputeNetworkBandwidth();
  if (bandwidth_estimate_ > 0) {
    // Don't ever try to use *all* of the network bandwidth! However, don't go
    // below the absolute minimum requirement either.
    constexpr double kGoodNetworkCitizenFactor = 0.8;
    const int usable_bandwidth = std::max<int>(
        kGoodNetworkCitizenFactor * bandwidth_estimate_, kMinRequiredBitrate);

    // See "congestion control" discussion in the class header comments for
    // BandwidthEstimator.
    if (usable_bandwidth > bandwidth_being_utilized_) {
      constexpr double kConservativeIncrease = 1.1;
      bandwidth_being_utilized_ = std::min<int>(
          bandwidth_being_utilized_ * kConservativeIncrease, usable_bandwidth);
    } else {
      bandwidth_being_utilized_ = usable_bandwidth;
    }

    // Repsect the user's maximum bitrate setting.
    bandwidth_being_utilized_ =
        std::min(bandwidth_being_utilized_, max_bitrate_);

    UpdateEncoderBitrates();
  } else {
    // There is no current bandwidth estimate. So, nothing should be adjusted.
  }

  next_task_.ScheduleFromNow([this] { ControlForNetworkCongestion(); },
                             kCongestionCheckInterval);
}

void LoopingFileSender::SendFileAgain() {
  OSP_LOG_INFO << "Sending " << path_ << " (starts in one second)...";
  TRACE_DEFAULT_SCOPED(TraceCategory::kStandaloneSender);

  OSP_DCHECK_EQ(num_capturers_running_, 0);
  num_capturers_running_ = 2;
  capture_start_time_ = latest_frame_time_ = env_->now() + seconds(1);
  audio_capturer_.emplace(env_, path_, audio_encoder_.num_channels(),
                          audio_encoder_.sample_rate(), capture_start_time_,
                          this);
  video_capturer_.emplace(env_, path_, capture_start_time_, this);

  next_task_.ScheduleFromNow([this] { ControlForNetworkCongestion(); },
                             kCongestionCheckInterval);
  console_update_task_.Schedule([this] { UpdateStatusOnConsole(); },
                                capture_start_time_);
}

void LoopingFileSender::OnAudioData(const float* interleaved_samples,
                                    int num_samples,
                                    Clock::time_point capture_time) {
  TRACE_DEFAULT_SCOPED(TraceCategory::kStandaloneSender);
  latest_frame_time_ = std::max(capture_time, latest_frame_time_);
  audio_encoder_.EncodeAndSend(interleaved_samples, num_samples, capture_time);
}

void LoopingFileSender::OnVideoFrame(const AVFrame& av_frame,
                                     Clock::time_point capture_time) {
  TRACE_DEFAULT_SCOPED(TraceCategory::kStandaloneSender);
  latest_frame_time_ = std::max(capture_time, latest_frame_time_);
  StreamingVp8Encoder::VideoFrame frame{};
  frame.width = av_frame.width - av_frame.crop_left - av_frame.crop_right;
  frame.height = av_frame.height - av_frame.crop_top - av_frame.crop_bottom;
  frame.yuv_planes[0] = av_frame.data[0] + av_frame.crop_left +
                        av_frame.linesize[0] * av_frame.crop_top;
  frame.yuv_planes[1] = av_frame.data[1] + av_frame.crop_left / 2 +
                        av_frame.linesize[1] * av_frame.crop_top / 2;
  frame.yuv_planes[2] = av_frame.data[2] + av_frame.crop_left / 2 +
                        av_frame.linesize[2] * av_frame.crop_top / 2;
  for (int i = 0; i < 3; ++i) {
    frame.yuv_strides[i] = av_frame.linesize[i];
  }
  // TODO(miu): Add performance metrics visual overlay (based on Stats
  // callback).
  video_encoder_.EncodeAndSend(frame, capture_time, {});
}

void LoopingFileSender::UpdateStatusOnConsole() {
  const Clock::duration elapsed = latest_frame_time_ - capture_start_time_;
  const auto seconds_part = to_seconds(elapsed);
  const auto millis_part = to_milliseconds(elapsed - seconds_part);
  // The control codes here attempt to erase the current line the cursor is
  // on, and then print out the updated status text. If the terminal does not
  // support simple ANSI escape codes, the following will still work, but
  // there might sometimes be old status lines not getting erased (i.e., just
  // partially overwritten).
  fprintf(stdout,
          "\r\x1b[2K\rLoopingFileSender: At %01" PRId64
          ".%03ds in file (est. network bandwidth: %d kbps). \n",
          static_cast<int64_t>(seconds_part.count()),
          static_cast<int>(millis_part.count()), bandwidth_estimate_ / 1024);
  fflush(stdout);

  console_update_task_.ScheduleFromNow([this] { UpdateStatusOnConsole(); },
                                       kConsoleUpdateInterval);
}

void LoopingFileSender::OnEndOfFile(SimulatedCapturer* capturer) {
  OSP_LOG_INFO << "The " << ToTrackName(capturer)
               << " capturer has reached the end of the media stream.";
  --num_capturers_running_;
  if (num_capturers_running_ == 0) {
    console_update_task_.Cancel();
    next_task_.Schedule([this] { SendFileAgain(); }, Alarm::kImmediately);
  }
}

void LoopingFileSender::OnError(SimulatedCapturer* capturer,
                                std::string message) {
  OSP_LOG_ERROR << "The " << ToTrackName(capturer)
                << " has failed: " << message;
  --num_capturers_running_;
  // If both fail, the application just pauses. This accounts for things like
  // "file not found" errors. However, if only one track fails, then keep
  // going.
}

const char* LoopingFileSender::ToTrackName(SimulatedCapturer* capturer) const {
  const char* which;
  if (capturer == &*audio_capturer_) {
    which = "audio";
  } else if (capturer == &*video_capturer_) {
    which = "video";
  } else {
    OSP_NOTREACHED();
    which = "";
  }
  return which;
}

}  // namespace cast
}  // namespace openscreen
