// Copyright 2019 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 "parser.h"

#include <lib/memory_barriers/memory_barriers.h>
#include <lib/trace/event.h>
#include <zircon/threads.h>

#include <limits>

#include "src/media/drivers/amlogic_decoder/decoder_core.h"
#include "src/media/drivers/amlogic_decoder/decoder_instance.h"
#include "src/media/drivers/amlogic_decoder/stream_buffer.h"
#include "src/media/drivers/amlogic_decoder/util.h"

namespace amlogic_decoder {

Parser::Parser(Owner* owner, zx::handle interrupt_handle)
    : owner_(owner), interrupt_handle_(std::move(interrupt_handle)) {
  zx::event::create(0, &parser_finished_event_);
}

Parser::~Parser() {
  if (interrupt_handle_) {
    zx_interrupt_destroy(interrupt_handle_.get());
    if (parser_interrupt_thread_.joinable())
      parser_interrupt_thread_.join();
  }
  CancelParsing();
  if (parser_input_) {
    io_buffer_release(parser_input_.get());
    parser_input_ = nullptr;
  }
  io_buffer_release(&search_pattern_);
}

// This parser handles MPEG elementary streams.
zx_status_t Parser::InitializeEsParser(DecoderInstance* instance) {
  assert(!owner_->is_parser_gated());
  Reset1Register::Get().FromValue(0).set_parser(true).WriteTo(owner_->mmio()->reset);
  FecInputControl::Get().FromValue(0).WriteTo(owner_->mmio()->demux);
  TsHiuCtl::Get()
      .ReadFrom(owner_->mmio()->demux)
      .set_use_hi_bsf_interface(false)
      .WriteTo(owner_->mmio()->demux);
  TsHiuCtl2::Get()
      .ReadFrom(owner_->mmio()->demux)
      .set_use_hi_bsf_interface(false)
      .WriteTo(owner_->mmio()->demux);
  TsHiuCtl3::Get()
      .ReadFrom(owner_->mmio()->demux)
      .set_use_hi_bsf_interface(false)
      .WriteTo(owner_->mmio()->demux);
  TsFileConfig::Get()
      .ReadFrom(owner_->mmio()->demux)
      .set_ts_hiu_enable(false)
      .WriteTo(owner_->mmio()->demux);
  ParserConfig::Get()
      .FromValue(0)
      .set_pfifo_empty_cnt(10)
      .set_max_es_write_cycle(1)
      .set_max_fetch_cycle(16)
      .WriteTo(owner_->mmio()->parser);
  PfifoRdPtr::Get().FromValue(0).WriteTo(owner_->mmio()->parser);
  PfifoWrPtr::Get().FromValue(0).WriteTo(owner_->mmio()->parser);
  constexpr uint32_t kEsStartCodePattern = 0x00000100;
  constexpr uint32_t kEsStartCodeMask = 0xffffff00;
  ParserSearchPattern::Get().FromValue(kEsStartCodePattern).WriteTo(owner_->mmio()->parser);
  ParserSearchMask::Get().FromValue(kEsStartCodeMask).WriteTo(owner_->mmio()->parser);

  ParserConfig::Get()
      .FromValue(0)
      .set_pfifo_empty_cnt(10)
      .set_max_es_write_cycle(1)
      .set_max_fetch_cycle(16)
      .set_startcode_width(ParserConfig::kWidth24)
      .set_pfifo_access_width(ParserConfig::kWidth8)
      .WriteTo(owner_->mmio()->parser);

  ParserControl::Get().FromValue(ParserControl::kAutoSearch).WriteTo(owner_->mmio()->parser);

  if (instance) {
    // Set up output fifo.
    uint32_t buffer_address = truncate_to_32(instance->stream_buffer()->buffer().phys_base());
    ParserVideoStartPtr::Get().FromValue(buffer_address).WriteTo(owner_->mmio()->parser);
    ParserVideoEndPtr::Get()
        .FromValue(truncate_to_32(buffer_address + instance->stream_buffer()->buffer().size() - 8))
        .WriteTo(owner_->mmio()->parser);

    ParserEsControl::Get()
        .ReadFrom(owner_->mmio()->parser)
        .set_video_manual_read_ptr_update(false)
        .set_video_write_endianness(0x7)
        .WriteTo(owner_->mmio()->parser);

    instance->core()->InitializeParserInput();
  }

  if (!io_buffer_is_valid(&search_pattern_)) {
    // 512 bytes includes some padding to force the parser to read it completely.
    constexpr uint32_t kSearchPatternSize = 512;
    auto search_pattern_vmo_result =
        owner_->AllocateContiguousSysmemVmo(kSearchPatternSize, 0, "AMLDecSearch");
    if (!search_pattern_vmo_result.is_ok()) {
      DECODE_ERROR("AllocateContiguousSysmemVmo failed");
      return ZX_ERR_NO_MEMORY;
    }
    auto& search_pattern_vmo = *search_pattern_vmo_result;
    zx_status_t status =
        io_buffer_init_vmo(&search_pattern_, owner_->bti()->get(), search_pattern_vmo.get(), 0,
                           IO_BUFFER_RW | IO_BUFFER_CONTIG);
    if (status != ZX_OK) {
      DECODE_ERROR("Failed to create search pattern buffer");
      return status;
    }
    SetIoBufferName(&search_pattern_, "ParserSearchPattern");

    uint8_t input_search_pattern[kSearchPatternSize] = {0, 0, 1, 0xff};

    memcpy(io_buffer_virt(&search_pattern_), input_search_pattern, kSearchPatternSize);
    io_buffer_cache_flush(&search_pattern_, 0, kSearchPatternSize);
    BarrierAfterFlush();
  }

  // This check exists so we can call InitializeEsParser() more than once, when
  // called from CodecImpl (indirectly via a CodecAdapter).
  if (!parser_interrupt_thread_.joinable()) {
    parser_interrupt_thread_ = std::thread([this]() {
      DLOG("Starting parser thread");
      while (true) {
        zx_time_t time;
        zx_status_t zx_status = zx_interrupt_wait(interrupt_handle_.get(), &time);
        if (zx_status != ZX_OK)
          return;

        std::lock_guard<std::mutex> lock(parser_running_lock_);
        if (!parser_running_)
          continue;
        assert(!owner_->is_parser_gated());
        // Continue holding parser_running_lock_ to ensure a cancel doesn't
        // execute while signaling is happening.
        auto status = ParserIntStatus::Get().ReadFrom(owner_->mmio()->parser);
        // Clear interrupt.
        status.WriteTo(owner_->mmio()->parser);
        DLOG("Got Parser interrupt status %x", status.reg_value());
        if (status.start_code_found()) {
          PfifoRdPtr::Get().FromValue(0).WriteTo(owner_->mmio()->parser);
          PfifoWrPtr::Get().FromValue(0).WriteTo(owner_->mmio()->parser);
          parser_finished_event_.signal(0, ZX_USER_SIGNAL_0);
        }
      }
    });
    owner_->SetThreadProfile(
        zx::unowned_thread(native_thread_get_zx_handle(parser_interrupt_thread_.native_handle())),
        ThreadRole::kParserIrq);
  }

  ParserIntStatus::Get().FromValue(0xffff).WriteTo(owner_->mmio()->parser);
  ParserIntEnable::Get().FromValue(0).set_host_en_start_code_found(true).WriteTo(
      owner_->mmio()->parser);

  return ZX_OK;
}

void Parser::SetOutputLocation(zx_paddr_t paddr, uint32_t len) {
  uint32_t buffer_start = truncate_to_32(paddr);
  ParserVideoStartPtr::Get().FromValue(buffer_start).WriteTo(owner_->mmio()->parser);
  // Prevent the parser from writing off the end of the buffer. Seems like it
  // probably needs to be 8-byte aligned.
  constexpr uint32_t kEndOfBufferOffset = 8;
  ParserVideoEndPtr::Get()
      .FromValue(buffer_start + len - kEndOfBufferOffset)
      .WriteTo(owner_->mmio()->parser);
  ParserVideoWp::Get().FromValue(buffer_start).WriteTo(owner_->mmio()->parser);
  // The read pointer isn't really used unless the output buffer wraps around.
  ParserVideoRp::Get().FromValue(buffer_start).WriteTo(owner_->mmio()->parser);

  // Keeps bytes in the same order as they were input.
  ParserEsControl::Get()
      .ReadFrom(owner_->mmio()->parser)
      .set_video_manual_read_ptr_update(true)
      .set_video_write_endianness(0x7)
      .WriteTo(owner_->mmio()->parser);
}

void Parser::SyncFromDecoderInstance(DecoderInstance* instance) {
  StreamBuffer* buffer = instance->stream_buffer();
  uint32_t buffer_phys_address = truncate_to_32(buffer->buffer().phys_base());
  size_t buffer_size = buffer->buffer().size();
  ZX_DEBUG_ASSERT(buffer_size <= std::numeric_limits<uint32_t>::max());
  uint32_t read_offset = instance->core()->GetReadOffset();
  uint32_t write_offset = instance->core()->GetStreamInputOffset();
  SyncFromBufferParameters(buffer_phys_address, static_cast<uint32_t>(buffer_size), read_offset,
                           write_offset);
}

void Parser::SyncToDecoderInstance(DecoderInstance* instance) {
  // The ParserVideoWp is the only ringbuffer register that should by changed by the process of
  // parsing.
  instance->core()->UpdateWritePointer(
      ParserVideoWp::Get().ReadFrom(owner_->mmio()->parser).reg_value());
}

void Parser::SyncFromBufferParameters(uint32_t buffer_phys_address, uint32_t buffer_size,
                                      uint32_t read_offset, uint32_t write_offset) {
  // Sync start and end pointers every time so using the same parser with multiple decoder instances
  // and/or for multiple purposes is less error-prone.
  ParserVideoStartPtr::Get().FromValue(buffer_phys_address).WriteTo(owner_->mmio()->parser);
  ParserVideoEndPtr::Get()
      .FromValue(buffer_phys_address + buffer_size - 8)
      .WriteTo(owner_->mmio()->parser);
  ParserVideoRp::Get().FromValue(read_offset + buffer_phys_address).WriteTo(owner_->mmio()->parser);
  ParserVideoWp::Get()
      .FromValue(write_offset + buffer_phys_address)
      .WriteTo(owner_->mmio()->parser);
  // Keeps bytes in the same order as they were input.
  ParserEsControl::Get()
      .ReadFrom(owner_->mmio()->parser)
      .set_video_manual_read_ptr_update(true)
      .set_video_write_endianness(0x7)
      .WriteTo(owner_->mmio()->parser);
}

zx_status_t Parser::ParseVideo(const void* data, uint32_t len) {
#if ZX_DEBUG_ASSERT_IMPLEMENTED
  {
    std::lock_guard<std::mutex> lock(parser_running_lock_);
    ZX_DEBUG_ASSERT(!parser_running_);
  }
#endif

  if (!parser_input_ || io_buffer_size(parser_input_.get(), 0) < len) {
    if (parser_input_) {
      io_buffer_release(parser_input_.get());
      parser_input_ = nullptr;
    }
    parser_input_ = std::make_unique<io_buffer_t>();
    auto parser_input_vmo_result =
        owner_->AllocateContiguousSysmemVmo(len, 0, "AMLDecoder_ParseVideo");
    if (!parser_input_vmo_result.is_ok()) {
      parser_input_ = nullptr;
      // AllocateContiguousSysmemVmo logged more detail just above this log output. The caller
      // doesn't need to know what caused allocation failure and should not retry the current call.
      DECODE_ERROR("AllocateContiguousSysmemVmo failed");
      return ZX_ERR_NO_MEMORY;
    }
    // io_buffer_init_vmo will duplicate the handle and parser_input_ will have its own handle
    // keeping the VMO alive.
    auto& parser_input_vmo = *parser_input_vmo_result;
    zx_status_t status =
        io_buffer_init_vmo(parser_input_.get(), owner_->bti()->get(), parser_input_vmo.get(), 0,
                           IO_BUFFER_RW | IO_BUFFER_CONTIG);
    if (status != ZX_OK) {
      parser_input_ = nullptr;
      DECODE_ERROR("Failed to create parser input buffer");
      return ZX_ERR_NO_MEMORY;
    }
    SetIoBufferName(parser_input_.get(), "ParserInput");
  }

  memcpy(io_buffer_virt(parser_input_.get()), data, len);
  io_buffer_cache_flush(parser_input_.get(), 0, len);
  BarrierAfterFlush();

  return ParseVideoPhysical(io_buffer_phys(parser_input_.get()), len);
}
// The caller of this method must know that the physical range is entirely
// within a VMO that's pinned for at least the duration of this call, and that
// the input data is already in RAM (not dirty in CPU cache).
zx_status_t Parser::ParseVideoPhysical(zx_paddr_t paddr, uint32_t len) {
  TRACE_DURATION("media", "Parser::ParseVideoPhysical");
  assert(!owner_->is_parser_gated());
#if ZX_DEBUG_ASSERT_IMPLEMENTED
  {
    std::lock_guard<std::mutex> lock(parser_running_lock_);
    ZX_DEBUG_ASSERT(!parser_running_);
  }
#endif

  PfifoRdPtr::Get().FromValue(0).WriteTo(owner_->mmio()->parser);
  PfifoWrPtr::Get().FromValue(0).WriteTo(owner_->mmio()->parser);

  // es_pack_size seems to be the amount of data that will be just copied through without attempting
  // to search for a start code.
  ParserControl::Get()
      .ReadFrom(owner_->mmio()->parser)
      .set_es_pack_size(len)
      .WriteTo(owner_->mmio()->parser);
  ParserControl::Get()
      .ReadFrom(owner_->mmio()->parser)
      .set_type(0)
      .set_write(true)
      .set_command(ParserControl::kAutoSearch)
      .WriteTo(owner_->mmio()->parser);

  ParserFetchAddr::Get().FromValue(truncate_to_32(paddr)).WriteTo(owner_->mmio()->parser);
  ParserFetchCmd::Get().FromValue(0).set_len(len).set_fetch_endian(7).WriteTo(
      owner_->mmio()->parser);

  // The parser finished interrupt shouldn't be signalled until after
  // es_pack_size data has been read.  The parser cancellation bit should not
  // be set because that bit is never set while parser_running_ is false
  // (ignoring transients while under parser_running_lock_).
  ZX_ASSERT(ZX_ERR_TIMED_OUT == parser_finished_event_.wait_one(ZX_USER_SIGNAL_0 | ZX_USER_SIGNAL_1,
                                                                zx::time(), nullptr));

  {
    std::lock_guard<std::mutex> lock(parser_running_lock_);
    parser_running_ = true;
  }

  // This data is after es_pack_size, so the parser will search for the search pattern in it.
  ParserFetchAddr::Get()
      .FromValue(truncate_to_32(io_buffer_phys(&search_pattern_)))
      .WriteTo(owner_->mmio()->parser);
  ParserFetchCmd::Get()
      .FromValue(0)
      .set_len(truncate_to_32(io_buffer_size(&search_pattern_, 0)))
      .set_fetch_endian(7)
      .WriteTo(owner_->mmio()->parser);

  return ZX_OK;
}

void Parser::TryStartCancelParsing() {
  {
    std::lock_guard<std::mutex> lock(parser_running_lock_);
    if (!parser_running_) {
      return;
    }
    // Regardless of whether this actually causes WaitForParsingCompleted() to
    // stop early, ZX_USER_SIGNAL_1 will become non-signaled when
    // parser_running_ goes back to false.
    parser_finished_event_.signal(0, ZX_USER_SIGNAL_1);
  }
}

zx_status_t Parser::WaitForParsingCompleted(zx_duration_t deadline) {
  TRACE_DURATION("media", "Parser::WaitForParsingCompleted");
  {
    std::lock_guard<std::mutex> lock(parser_running_lock_);
    ZX_DEBUG_ASSERT(parser_running_);
  }
  zx_signals_t observed = 0;
  zx_status_t status = parser_finished_event_.wait_one(
      ZX_USER_SIGNAL_0 | ZX_USER_SIGNAL_1, zx::deadline_after(zx::duration(deadline)), &observed);
  if (status != ZX_OK) {
    LOG(ERROR, "parser_finished_event_.wait_one failed status: %d observed %x", status, observed);
    return status;
  }
  if (observed & ZX_USER_SIGNAL_1) {
    // Reporting interruption wins if both bits are observed.
    //
    // The CancelParsing() will clear both ZX_USER_SIGNAL_0 (whether set or not)
    // and ZX_USER_SIGNAL_1.
    //
    // The caller must still call CancelParsing(), as with any error returned
    // from this method.
    LOG(DEBUG, "observed & ZX_USER_SIGNAL_1");
    return ZX_ERR_CANCELED;
  }

  // Observed reports _all_ the signals, so only check the one we know is
  // supposed to be set in observed at this point.
  ZX_DEBUG_ASSERT(observed & ZX_USER_SIGNAL_0);
  std::lock_guard<std::mutex> lock(parser_running_lock_);
  parser_running_ = false;
  // ZX_USER_SIGNAL_1 must be un-signaled while parser_running_ is false.
  parser_finished_event_.signal(ZX_USER_SIGNAL_0 | ZX_USER_SIGNAL_1, 0);
  // Ensure the parser finishes before parser_input_ is written into again or
  // released. dsb is needed instead of the dmb we get from the mutex.
  BarrierBeforeRelease();
  return ZX_OK;
}

void Parser::CancelParsing() {
  std::lock_guard<std::mutex> lock(parser_running_lock_);
  if (!parser_running_) {
    return;
  }
  assert(!owner_->is_parser_gated());

  LOG(DEBUG, "Parser cancelled");
  parser_running_ = false;

  ParserFetchCmd::Get().FromValue(0).WriteTo(owner_->mmio()->parser);
  // Ensure the parser finishes before parser_input_ is written into again or
  // released. dsb is needed instead of the dmb we get from the mutex.
  BarrierBeforeRelease();
  // Clear the parser interrupt to ensure that if the parser happened to
  // finish before the ParserFetchCmd was processed that the finished event
  // won't be signaled accidentally for the next parse.
  auto status = ParserIntStatus::Get().ReadFrom(owner_->mmio()->parser);
  // Writing 1 to a bit clears it.
  status.WriteTo(owner_->mmio()->parser);
  // ZX_USER_SIGNAL_1 must be un-signaled while parser_running_ is false.
  parser_finished_event_.signal(ZX_USER_SIGNAL_0 | ZX_USER_SIGNAL_1, 0);
}

}  // namespace amlogic_decoder
