// Copyright 2014 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 "media/cast/test/receiver/framer.h"

#include "base/logging.h"
#include "media/cast/constants.h"

namespace media {
namespace cast {

Framer::Framer(const base::TickClock* clock,
               RtpPayloadFeedback* incoming_payload_feedback,
               uint32_t ssrc,
               bool decoder_faster_than_max_frame_rate,
               int max_unacked_frames)
    : decoder_faster_than_max_frame_rate_(decoder_faster_than_max_frame_rate),
      cast_msg_builder_(clock,
                        incoming_payload_feedback,
                        this,
                        ssrc,
                        decoder_faster_than_max_frame_rate,
                        max_unacked_frames),
      waiting_for_key_(true),
      last_released_frame_(FrameId::first() - 1),
      newest_frame_id_(FrameId::first() - 1) {
  DCHECK(incoming_payload_feedback) << "Invalid argument";
}

Framer::~Framer() = default;

bool Framer::InsertPacket(const uint8_t* payload_data,
                          size_t payload_size,
                          const RtpCastHeader& rtp_header,
                          bool* duplicate) {
  *duplicate = false;

  if (rtp_header.is_key_frame && waiting_for_key_) {
    last_released_frame_ = rtp_header.frame_id - 1;
    waiting_for_key_ = false;
  }

  VLOG(1) << "InsertPacket frame:" << rtp_header.frame_id
          << " packet:" << static_cast<int>(rtp_header.packet_id)
          << " max packet:" << static_cast<int>(rtp_header.max_packet_id);

  if ((rtp_header.frame_id <= last_released_frame_) && !waiting_for_key_) {
    // Packet is too old.
    return false;
  }

  // Update the last received frame id.
  if (rtp_header.frame_id > newest_frame_id_) {
    newest_frame_id_ = rtp_header.frame_id;
  }

  // Insert packet.
  const auto it = frames_.find(rtp_header.frame_id);
  FrameBuffer* buffer;
  if (it == frames_.end()) {
    buffer = new FrameBuffer();
    frames_.insert(std::make_pair(rtp_header.frame_id,
                                  std::unique_ptr<FrameBuffer>(buffer)));
  } else {
    buffer = it->second.get();
  }
  if (!buffer->InsertPacket(payload_data, payload_size, rtp_header)) {
    VLOG(3) << "Packet already received, ignored: frame " << rtp_header.frame_id
            << ", packet " << rtp_header.packet_id;
    *duplicate = true;
    return false;
  }

  return buffer->Complete();
}

// This does not release the frame.
bool Framer::GetEncodedFrame(EncodedFrame* frame,
                             bool* next_frame,
                             bool* have_multiple_decodable_frames) {
  *have_multiple_decodable_frames = HaveMultipleDecodableFrames();

  // Find frame id.
  FrameBuffer* buffer = FindNextFrameForRelease();
  if (buffer) {
    // We have our next frame.
    *next_frame = true;
  } else {
    // Check if we can skip frames when our decoder is too slow.
    if (!decoder_faster_than_max_frame_rate_)
      return false;

    buffer = FindOldestDecodableFrame();
    if (!buffer)
      return false;
    *next_frame = false;
  }

  return buffer->AssembleEncodedFrame(frame);
}

void Framer::AckFrame(FrameId frame_id) {
  VLOG(2) << "ACK frame " << frame_id;
  cast_msg_builder_.CompleteFrameReceived(frame_id);
}

void Framer::ReleaseFrame(FrameId frame_id) {
  const auto it = frames_.begin();
  const bool skipped_old_frame = it->first < frame_id;
  frames_.erase(it, frames_.upper_bound(frame_id));
  last_released_frame_ = frame_id;
  if (skipped_old_frame)
    cast_msg_builder_.UpdateCastMessage();
}

bool Framer::TimeToSendNextCastMessage(base::TimeTicks* time_to_send) {
  return cast_msg_builder_.TimeToSendNextCastMessage(time_to_send);
}

void Framer::SendCastMessage() {
  cast_msg_builder_.UpdateCastMessage();
}

FrameBuffer* Framer::FindNextFrameForRelease() {
  for (const auto& entry : frames_) {
    if (entry.second->Complete() && IsNextFrameForRelease(*entry.second))
      return entry.second.get();
  }
  return nullptr;
}

FrameBuffer* Framer::FindOldestDecodableFrame() {
  for (const auto& entry : frames_) {
    if (entry.second->Complete() && IsDecodableFrame(*entry.second))
      return entry.second.get();
  }
  return nullptr;
}

bool Framer::HaveMultipleDecodableFrames() const {
  bool found_one = false;
  for (const auto& entry : frames_) {
    if (entry.second->Complete() && IsDecodableFrame(*entry.second)) {
      if (found_one)
        return true;  // Found another.
      else
        found_one = true;  // Found first one.  Continue search for another.
    }
  }
  return false;
}

bool Framer::Empty() const {
  return frames_.empty();
}

int Framer::NumberOfCompleteFrames() const {
  int count = 0;
  for (const auto& entry : frames_) {
    if (entry.second->Complete())
      ++count;
  }
  return count;
}

bool Framer::FrameExists(FrameId frame_id) const {
  return frames_.end() != frames_.find(frame_id);
}

void Framer::GetMissingPackets(FrameId frame_id,
                               bool last_frame,
                               PacketIdSet* missing_packets) const {
  const auto it = frames_.find(frame_id);
  if (it == frames_.end())
    return;

  it->second->GetMissingPackets(last_frame, missing_packets);
}

bool Framer::IsNextFrameForRelease(const FrameBuffer& buffer) const {
  if (waiting_for_key_ && !buffer.is_key_frame())
    return false;
  return (last_released_frame_ + 1) == buffer.frame_id();
}

bool Framer::IsDecodableFrame(const FrameBuffer& buffer) const {
  if (buffer.is_key_frame())
    return true;
  if (waiting_for_key_)
    return false;
  // Self-reference?
  if (buffer.last_referenced_frame_id() == buffer.frame_id())
    return true;

  // Current frame is not necessarily referencing the last frame.
  // Has the reference frame been released already?
  return buffer.last_referenced_frame_id() <= last_released_frame_;
}

}  // namespace cast
}  // namespace media
