// 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.

#ifndef GARNET_DRIVERS_VIDEO_AMLOGIC_DECODER_CODEC_ADAPTER_H264_H_
#define GARNET_DRIVERS_VIDEO_AMLOGIC_DECODER_CODEC_ADAPTER_H264_H_

#include <fbl/macros.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/media/codec_impl/codec_adapter.h>
#include <lib/zx/bti.h>

class AmlogicVideo;
struct CodecFrame;
class DeviceCtx;
struct VideoFrame;
class CodecAdapterH264 : public CodecAdapter {
 public:
  explicit CodecAdapterH264(std::mutex& lock,
                            CodecAdapterEvents* codec_adapter_events,
                            DeviceCtx* device);
  ~CodecAdapterH264();

  bool IsCoreCodecRequiringOutputConfigForFormatDetection() override;
  void CoreCodecInit(const fuchsia::media::FormatDetails&
                         initial_input_format_details) override;
  void CoreCodecStartStream() override;
  void CoreCodecQueueInputFormatDetails(
      const fuchsia::media::FormatDetails& per_stream_override_format_details)
      override;
  void CoreCodecQueueInputPacket(CodecPacket* packet) override;
  void CoreCodecQueueInputEndOfStream() override;
  void CoreCodecStopStream() override;
  void CoreCodecAddBuffer(CodecPort port, const CodecBuffer* buffer) override;
  void CoreCodecConfigureBuffers(
      CodecPort port,
      const std::vector<std::unique_ptr<CodecPacket>>& packets) override;
  void CoreCodecRecycleOutputPacket(CodecPacket* packet) override;
  void CoreCodecEnsureBuffersNotConfigured(CodecPort port) override;
  std::unique_ptr<const fuchsia::media::StreamOutputConfig>
  CoreCodecBuildNewOutputConfig(
      uint64_t stream_lifetime_ordinal,
      uint64_t new_output_buffer_constraints_version_ordinal,
      uint64_t new_output_format_details_version_ordinal,
      bool buffer_constraints_action_required) override;
  void CoreCodecMidStreamOutputBufferReConfigPrepare() override;
  void CoreCodecMidStreamOutputBufferReConfigFinish() override;

 private:
  void PostSerial(async_dispatcher_t* dispatcher, fit::closure to_run);
  void PostToInputProcessingThread(fit::closure to_run);
  void QueueInputItem(CodecInputItem input_item);
  CodecInputItem DequeueInputItem();
  void ProcessInput();
  bool ParseAndDeliverCodecOobBytes();
  // If parsing something whose format depends on is_avcc_, use this method.
  bool ParseVideo(const uint8_t* data, uint32_t length);
  // If parsing something that's known to be in AVCC format, such as a bunch of
  // 0x00 without start codes or emulation prevention bytes, use this method.
  bool ParseVideoAvcc(const uint8_t* data, uint32_t length);
  // If parsing something that's known to be in AnnexB format, such as the
  // end-of-stream marker data, use this method.
  bool ParseVideoAnnexB(const uint8_t* data, uint32_t length);
  zx_status_t InitializeFramesHandler(::zx::bti bti, uint32_t frame_count,
                                      uint32_t width, uint32_t height,
                                      uint32_t stride, uint32_t display_width,
                                      uint32_t display_height, bool has_sar,
                                      uint32_t sar_width, uint32_t sar_height);

  void OnCoreCodecFailStream();
  CodecPacket* GetFreePacket(uint32_t buffer_index);

  DeviceCtx* device_ = nullptr;
  AmlogicVideo* video_ = nullptr;

  fuchsia::media::FormatDetails initial_input_format_details_;
  fuchsia::media::FormatDetails latest_input_format_details_;

  // Currently, AmlogicVideo::ParseVideo() can indirectly block on availability
  // of output buffers to make space in the ring buffer the parser is outputting
  // into, so avoid calling ParseVideo() on shared_fidl_thread() since the
  // shared_fidl_thread() is needed for output buffers to become available.  We
  // use processing_loop_ (aka processing_thread_) to call ParseVideo().
  //
  // Only StreamControl ever adds anything to input_queue_.  Only
  // processing_thread_ ever removes anything from input_queue_, including when
  // stopping.
  async::Loop input_processing_loop_;
  thrd_t input_processing_thread_ = 0;
  bool is_process_input_queued_ = false;

  // Skip any further processing in ProcessInput().
  bool is_cancelling_input_processing_ = false;

  std::vector<const CodecBuffer*> all_output_buffers_;
  std::vector<CodecPacket*> all_output_packets_;

  uint32_t packet_count_total_ = 0;
  uint32_t width_ = 0;
  uint32_t height_ = 0;
  uint32_t stride_ = 0;
  uint32_t display_width_ = 0;
  uint32_t display_height_ = 0;
  bool has_sar_ = false;
  uint32_t sar_width_ = 0;
  uint32_t sar_height_ = 0;

  // Output frames get a PTS based on looking up the output frame's input stream
  // offset via the PtsManager.  For that to work we have to feed the input PTSs
  // into the PtsManager by their input stream offset.  This member tracks the
  // cumulative input stream offset. This is implicitly the same count of bytes
  // so far that the amlogic firmware will accumulate and stamp on output
  // frames.  This counts all bytes delivered to the amlogic firmware, including
  // start code bytes.
  uint64_t parsed_video_size_ = 0;
  // If true, the core codec will need the oob_bytes info, if any.  The
  // core codec in this case wants the info in annex B form in-band, not
  // AVCC/avcC form out-of-band.
  bool is_input_format_details_pending_ = false;

  // For any new stream, remains false until proven otherwise.  If this is true
  // we have to add start code emulation prevention bytes, and replace AVCC
  // nal_length fields (themselves usually 4 bytes long but not always) with
  // start codes (out-of-place conversion).
  bool is_avcc_ = false;
  // This is the length in bytes of the pseudo_nal_length field, which in turn
  // has the length of a pseudo_nal in bytes.  Feel free to suggest a better
  // name for this field, but I want to strongly emphasize that it's the length
  // of a length field, not itself directly the length...
  //
  // Typically 4 if is_avcc_, but not always.
  uint32_t pseudo_nal_length_field_bytes_ = 0;

  bool is_input_end_of_stream_queued_ = false;

  bool is_stream_failed_ = false;

  CodecAdapterH264() = delete;
  DISALLOW_COPY_ASSIGN_AND_MOVE(CodecAdapterH264);
};

#endif  // GARNET_DRIVERS_VIDEO_AMLOGIC_DECODER_CODEC_ADAPTER_H264_H_
