/*
 *  Copyright (c) 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 "modules/video_coding/loss_notification_controller.h"

#include "rtc_base/checks.h"
#include "rtc_base/logging.h"

namespace webrtc {
namespace {
// Keep a container's size no higher than |max_allowed_size|, by paring its size
// down to |target_size| whenever it has more than |max_allowed_size| elements.
template <typename Container>
void PareDown(Container* container,
              size_t max_allowed_size,
              size_t target_size) {
  if (container->size() > max_allowed_size) {
    const size_t entries_to_delete = container->size() - target_size;
    auto erase_to = container->begin();
    std::advance(erase_to, entries_to_delete);
    container->erase(container->begin(), erase_to);
    RTC_DCHECK_EQ(container->size(), target_size);
  }
}
}  // namespace

LossNotificationController::LossNotificationController(
    KeyFrameRequestSender* key_frame_request_sender,
    LossNotificationSender* loss_notification_sender)
    : key_frame_request_sender_(key_frame_request_sender),
      loss_notification_sender_(loss_notification_sender),
      current_frame_potentially_decodable_(true) {
  RTC_DCHECK(key_frame_request_sender_);
  RTC_DCHECK(loss_notification_sender_);
}

LossNotificationController::~LossNotificationController() = default;

void LossNotificationController::OnReceivedPacket(const VCMPacket& packet) {
  RTC_DCHECK_RUN_ON(&sequence_checker_);

  if (!packet.generic_descriptor) {
    RTC_LOG(LS_WARNING) << "Generic frame descriptor missing. Buggy remote? "
                           "Misconfigured local?";
    return;
  }

  // Ignore repeated or reordered packets.
  // TODO(bugs.webrtc.org/10336): Handle packet reordering.
  if (last_received_seq_num_ &&
      !AheadOf(packet.seqNum, *last_received_seq_num_)) {
    return;
  }

  DiscardOldInformation();  // Prevent memory overconsumption.

  const bool seq_num_gap =
      last_received_seq_num_ &&
      packet.seqNum != static_cast<uint16_t>(*last_received_seq_num_ + 1u);

  last_received_seq_num_ = packet.seqNum;

  if (packet.generic_descriptor->FirstPacketInSubFrame()) {
    const uint16_t frame_id = packet.generic_descriptor->FrameId();
    const int64_t unwrapped_frame_id = frame_id_unwrapper_.Unwrap(frame_id);

    // Ignore repeated or reordered frames.
    // TODO(TODO(bugs.webrtc.org/10336): Handle frame reordering.
    if (last_received_unwrapped_frame_id_ &&
        unwrapped_frame_id <= *last_received_unwrapped_frame_id_) {
      RTC_LOG(LS_WARNING) << "Repeated or reordered frame ID (" << frame_id
                          << ").";
      return;
    }

    last_received_unwrapped_frame_id_ = unwrapped_frame_id;

    const bool intra_frame =
        packet.generic_descriptor->FrameDependenciesDiffs().empty();
    // Generic Frame Descriptor does not current allow us to distinguish
    // whether an intra frame is a key frame.
    // We therefore assume all intra frames are key frames.
    const bool key_frame = intra_frame;
    if (key_frame) {
      // Subsequent frames may not rely on frames before the key frame.
      decodable_unwrapped_frame_ids_.clear();
      current_frame_potentially_decodable_ = true;
    } else {
      const bool all_dependencies_decodable = AllDependenciesDecodable(
          unwrapped_frame_id,
          packet.generic_descriptor->FrameDependenciesDiffs());
      current_frame_potentially_decodable_ = all_dependencies_decodable;
      if (seq_num_gap || !current_frame_potentially_decodable_) {
        HandleLoss(packet.seqNum, current_frame_potentially_decodable_);
      }
    }
  } else if (seq_num_gap || !current_frame_potentially_decodable_) {
    current_frame_potentially_decodable_ = false;
    // We allow sending multiple loss notifications for a single frame
    // even if only one of its packets is lost. We do this because the bigger
    // the frame, the more likely it is to be non-discardable, and therefore
    // the more robust we wish to be to loss of the feedback messages.
    HandleLoss(packet.seqNum, false);
  }
}

void LossNotificationController::OnAssembledFrame(
    uint16_t first_seq_num,
    uint16_t frame_id,
    bool discardable,
    rtc::ArrayView<const uint16_t> frame_dependency_diffs) {
  RTC_DCHECK_RUN_ON(&sequence_checker_);

  DiscardOldInformation();  // Prevent memory overconsumption.

  if (discardable) {
    return;
  }

  const int64_t unwrapped_frame_id = frame_id_unwrapper_.Unwrap(frame_id);
  if (!AllDependenciesDecodable(unwrapped_frame_id, frame_dependency_diffs)) {
    return;
  }

  last_decodable_non_discardable_.emplace(first_seq_num);
  const auto it = decodable_unwrapped_frame_ids_.insert(unwrapped_frame_id);
  RTC_DCHECK(it.second);
}

void LossNotificationController::DiscardOldInformation() {
  constexpr size_t kExpectedKeyFrameIntervalFrames = 3000;
  constexpr size_t kMaxSize = 2 * kExpectedKeyFrameIntervalFrames;
  constexpr size_t kTargetSize = kExpectedKeyFrameIntervalFrames;
  PareDown(&decodable_unwrapped_frame_ids_, kMaxSize, kTargetSize);
}

bool LossNotificationController::AllDependenciesDecodable(
    int64_t unwrapped_frame_id,
    rtc::ArrayView<const uint16_t> frame_dependency_diffs) const {
  RTC_DCHECK_RUN_ON(&sequence_checker_);

  // Due to packet reordering, frame buffering and asynchronous decoders, it is
  // infeasible to make reliable conclusions on the decodability of a frame
  // immediately when it arrives. We use the following assumptions:
  // * Intra frames are decodable.
  // * Inter frames are decodable if all of their references were decodable.
  // One possibility that is ignored, is that the packet may be corrupt.

  for (uint16_t frame_dependency_diff : frame_dependency_diffs) {
    const int64_t unwrapped_ref_frame_id =
        unwrapped_frame_id - frame_dependency_diff;

    const auto ref_frame_it =
        decodable_unwrapped_frame_ids_.find(unwrapped_ref_frame_id);
    if (ref_frame_it == decodable_unwrapped_frame_ids_.end()) {
      // Reference frame not decodable.
      return false;
    }
  }

  return true;
}

void LossNotificationController::HandleLoss(uint16_t last_received_seq_num,
                                            bool decodability_flag) {
  RTC_DCHECK_RUN_ON(&sequence_checker_);

  if (last_decodable_non_discardable_) {
    RTC_DCHECK(AheadOf(last_received_seq_num,
                       last_decodable_non_discardable_->first_seq_num));
    loss_notification_sender_->SendLossNotification(
        last_decodable_non_discardable_->first_seq_num, last_received_seq_num,
        decodability_flag);
  } else {
    key_frame_request_sender_->RequestKeyFrame();
  }
}
}  //  namespace webrtc
