// 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/trace/event.h>

#include <limits>

#include "decoder_core.h"
#include "decoder_instance.h"
#include "src/media/lib/memory_barriers/memory_barriers.h"
#include "stream_buffer.h"
#include "util.h"

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(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;
    zx_status_t status = io_buffer_init(&search_pattern_, owner_->bti()->get(), kSearchPatternSize,
                                        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);
        }
      }
    });
  }

  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, 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>();
    zx_status_t status = io_buffer_init(parser_input_.get(), owner_->bti()->get(), len,
                                        IO_BUFFER_RW | IO_BUFFER_CONTIG);
    if (status != ZX_OK) {
      parser_input_ = nullptr;
      DECODE_ERROR("Failed to create input file");
      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(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);
}
