// Copyright 2018 The Fuchsia 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 "pts_manager.h"

#include <inttypes.h>
#include <zircon/assert.h>

#include "lib/media/extend_bits/extend_bits.h"
#include "macros.h"

#ifndef AMLOGIC_PTS_DLOG_ENABLE
#define AMLOGIC_PTS_DLOG_ENABLE 0
#endif

#define PTS_DLOG(fmt, ...)           \
  do {                               \
    if (AMLOGIC_PTS_DLOG_ENABLE) {   \
      LOG(INFO, fmt, ##__VA_ARGS__); \
    }                                \
  } while (0)

namespace amlogic_decoder {

// h264 has HW stream offset counter with 0xfffffff max - 28 bit - 256 MiB cycle period
// vp9 has a 32 bit stream offset counter.
void PtsManager::SetLookupBitWidth(uint32_t lookup_bit_width) {
  PTS_DLOG("SetLookupBitWidth() lookup_bit_width: %u", lookup_bit_width);
  std::lock_guard<std::mutex> lock(lock_);
  ZX_DEBUG_ASSERT(lookup_bit_width_ == 64 && lookup_bit_width != 64);
  lookup_bit_width_ = lookup_bit_width;
}

void PtsManager::InsertPts(uint64_t offset, bool has_pts, uint64_t pts) {
  PTS_DLOG("InsertPts() offset: 0x%" PRIx64 " has_pts: %d pts: %" PRIx64, offset, has_pts, pts);
  std::lock_guard<std::mutex> lock(lock_);

  ZX_DEBUG_ASSERT(has_pts || !pts);

  // caller should not insert duplicates
  ZX_DEBUG_ASSERT(offset_to_result_.find(offset) == offset_to_result_.end());
  // caller should set offsets in order
  ZX_DEBUG_ASSERT(offset_to_result_.empty() || offset > offset_to_result_.rbegin()->first);

  offset_to_result_.emplace(std::make_pair(offset, LookupResult(false, has_pts, pts)));

  // Erase the oldest PTSes.  See the definition of kMaxEntriesToKeep for how we know this will be
  // enough entries.
  while (offset_to_result_.size() > kMaxEntriesToKeep) {
    offset_to_result_.erase(offset_to_result_.begin());
  }
}

void PtsManager::SetEndOfStreamOffset(uint64_t end_of_stream_offset) {
  PTS_DLOG("SetEndOfStreamOffset() end_of_stream_offset: %" PRIx64, end_of_stream_offset);
  std::lock_guard<std::mutex> lock(lock_);

  // caller should not insert duplicates
  ZX_DEBUG_ASSERT(offset_to_result_.find(end_of_stream_offset) == offset_to_result_.end());
  // caller should set offsets in order
  ZX_DEBUG_ASSERT(offset_to_result_.empty() ||
                  end_of_stream_offset > (*offset_to_result_.rbegin()).first);

  // caller should only set end of stream offset once
  ZX_DEBUG_ASSERT(offset_to_result_.empty() ||
                  !(*offset_to_result_.rbegin()).second.is_end_of_stream());

  offset_to_result_.emplace(std::make_pair(end_of_stream_offset, LookupResult(true, false, 0)));
}

const PtsManager::LookupResult PtsManager::Lookup(uint64_t offset) {
  std::lock_guard<std::mutex> lock(lock_);
  ZX_DEBUG_ASSERT(lookup_bit_width_ == 64 ||
                  offset < (static_cast<uint64_t>(1) << lookup_bit_width_));

  // last_inserted_offset is known-good in the sense that it's known to be a valid full-width
  // uint64_t input stream offset.  We prefer to anchor on this value rather than incrementally
  // anchoring on the last bit-extended offset passed in as a query, since we know with higher
  // certainty that this value is correct (and both those options are fairly near the bit-extended
  // form of the logical offset coming into this method).
  uint64_t last_inserted_offset = GetLastInsertedOffset();

  // Basically we're determining whether offset is logically above or logically below
  // last_inserted_offset.
  offset = ExtendBits(last_inserted_offset, offset, lookup_bit_width_);

  auto it = offset_to_result_.upper_bound(offset);
  // Check if this offset is < any element in the list.
  if (it == offset_to_result_.begin()) {
    PTS_DLOG("it == offset_to_result_.begin() -- offset: 0x%" PRIx64, offset);
    return PtsManager::LookupResult(false, false, 0);
  }
  // Decrement to find the pts corresponding to the last offset <= |offset|.
  --it;

  if (AMLOGIC_PTS_DLOG_ENABLE) {
    const PtsManager::LookupResult& result = it->second;
    if (result.is_end_of_stream()) {
      PTS_DLOG("Lookup() offset: 0x%" PRIx64 " EOS", offset);
    } else {
      PTS_DLOG("Lookup() offset: 0x%" PRIx64 " has_pts: %d pts: 0x%" PRIx64
               " offset - found: 0x%" PRIx64 " entries beyond found: %u",
               offset, result.has_pts(), result.pts(), offset - it->first,
               CountEntriesBeyondLocked(it->first));
    }
  }

  return it->second;
}

uint32_t PtsManager::CountEntriesBeyond(uint64_t threshold_offset) const {
  std::lock_guard<std::mutex> lock(lock_);
  return CountEntriesBeyondLocked(threshold_offset);
}

uint32_t PtsManager::CountEntriesBeyondLocked(uint64_t threshold_offset) const {
  // Shorter bit width not implemented for this method yet.
  ZX_DEBUG_ASSERT(lookup_bit_width_ == 64);
  auto it = offset_to_result_.upper_bound(threshold_offset);
  uint32_t count = 0;
  while (it != offset_to_result_.end()) {
    ++it;
    ++count;
  }
  return count;
}

// The last inserted offset is offset_to_result_.rbegin()->first, unless empty() in which case
// logically 0.
uint64_t PtsManager::GetLastInsertedOffset() {
  if (offset_to_result_.empty()) {
    return 0;
  }
  return offset_to_result_.rbegin()->first;
}

}  // namespace amlogic_decoder
