// Copyright 2020 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 "src/media/drivers/amlogic_encoder/codec_adapter_h264.h"

#include <lib/fidl/cpp/clone.h>
#include <lib/media/codec_impl/codec_frame.h>
#include <lib/zx/bti.h>

#include "src/media/drivers/amlogic_encoder/device_ctx.h"
#include "src/media/drivers/amlogic_encoder/macros.h"

// TODO(afoxley) adjust to higher value when we get real data flowing
constexpr uint32_t kOutputBufferMinSizeBytes = 4 * 4096;
constexpr uint32_t kOutputBufferMaxSizeBytes = 4 * 4096;
constexpr uint32_t kOutputMinBufferCountForCamping = 2;
// constexpr uint32_t kOutputMinBufferCountForDedicatedSlack = 1;
constexpr uint32_t kOutputMaxBufferCount = 0;  // unbounded
constexpr uint32_t kInputMinBufferCountForCamping = 2;
constexpr uint32_t kInputMaxBufferCount = 0;  // unbounded

constexpr uint64_t kInputBufferConstraintsVersionOrdinal = 1;
constexpr uint64_t kInputDefaultBufferConstraintsVersionOrdinal =
    kInputBufferConstraintsVersionOrdinal;

constexpr uint32_t kInputPacketCountForServerMin = 2;
constexpr uint32_t kInputPacketCountForServerRecommended = 3;
constexpr uint32_t kInputPacketCountForServerRecommendedMax = 3;
constexpr uint32_t kInputPacketCountForServerMax = 3;
constexpr uint32_t kInputDefaultPacketCountForServer = kInputPacketCountForServerRecommended;

constexpr uint32_t kInputPacketCountForClientMin = 2;
constexpr uint32_t kInputPacketCountForClientMax = std::numeric_limits<uint32_t>::max();
constexpr uint32_t kInputDefaultPacketCountForClient = 3;

constexpr uint32_t kInputPerPacketBufferBytesMin = 8 * 1024;
constexpr uint32_t kInputPerPacketBufferBytesRecommended = 1920 * 1080 * 3 / 2;
constexpr uint32_t kInputPerPacketBufferBytesMax = 1920 * 1080 * 3 / 2;
constexpr uint32_t kInputDefaultPerPacketBufferBytes = kInputPerPacketBufferBytesRecommended;

constexpr bool kInputSingleBufferModeAllowed = false;
constexpr bool kInputDefaultSingleBufferMode = false;

CodecAdapterH264::CodecAdapterH264(std::mutex& lock, CodecAdapterEvents* codec_adapter_events,
                                   DeviceCtx* device)
    : CodecAdapter(lock, codec_adapter_events),
      device_(device),
      input_processing_loop_(&kAsyncLoopConfigNoAttachToCurrentThread) {
  ZX_DEBUG_ASSERT(device_);
}

CodecAdapterH264::~CodecAdapterH264() {
  // nothing else to do here, at least not until we aren't calling PowerOff() in
  // CoreCodecStopStream().
}

bool CodecAdapterH264::IsCoreCodecRequiringOutputConfigForFormatDetection() { return false; }

bool CodecAdapterH264::IsCoreCodecMappedBufferUseful(CodecPort port) {
  if (port == kInputPort) {
    return false;
  } else {
    // we likely want to be able to copy the encoded output to support sending a NAL across multiple
    // output packets, with each new NAL starting a fresh packet so it gets a place to put its PTS
    return true;
  }
}

bool CodecAdapterH264::IsCoreCodecHwBased(CodecPort port) { return true; }

zx::unowned_bti CodecAdapterH264::CoreCodecBti() { return zx::unowned_bti(device_->bti()); }

void CodecAdapterH264::CoreCodecInit(
    const fuchsia::media::FormatDetails& initial_input_format_details) {
  ZX_DEBUG_ASSERT(!output_sink_);
  zx_status_t result = input_processing_loop_.StartThread(
      "CodecAdapterH264::input_processing_thread_", &input_processing_thread_);
  if (result != ZX_OK) {
    events_->onCoreCodecFailCodec(
        "In CodecAdapterH264::CoreCodecInit(), StartThread() failed (input)");
    return;
  }

  initial_input_format_details_ = fidl::Clone(initial_input_format_details);
  latest_input_format_details_ = fidl::Clone(initial_input_format_details);

  if (!latest_input_format_details_.has_domain() ||
      !latest_input_format_details_.domain().is_video() ||
      !latest_input_format_details_.domain().video().is_uncompressed()) {
    events_->onCoreCodecFailCodec(
        "In CodecAdapterH264::CoreCodecInit(), StartThread() failed (input)");
    return;
  }

  width_ = latest_input_format_details_.domain().video().uncompressed().image_format.display_width;
  height_ =
      latest_input_format_details_.domain().video().uncompressed().image_format.display_height;
  min_stride_ = width_;

  output_sink_.emplace(/*sender=*/
                       [this](CodecPacket* output_packet) {
                         events_->onCoreCodecOutputPacket(output_packet,
                                                          /*error_detected_before=*/false,
                                                          /*error_detected_during=*/false);
                         return OutputSink::kSuccess;
                       },
                       /*writer_thread=*/input_processing_thread_);

  result = device_->EncoderInit(initial_input_format_details_);
  if (result != ZX_OK) {
    events_->onCoreCodecFailCodec("In CodecAdapterH264::CoreCodecInit(), EncoderInit failed");
    return;
  }
}

void CodecAdapterH264::CoreCodecStartStream() {
  ZX_DEBUG_ASSERT(!output_sink_->HasPendingPacket());
  // The keep_data true keeps any free buffers and free packets.
  output_sink_->Reset(/*keep_data=*/true);
}

void CodecAdapterH264::CoreCodecQueueInputFormatDetails(
    const fuchsia::media::FormatDetails& per_stream_override_format_details) {
  // TODO(dustingreen): Consider letting the client specify profile/level info
  // in the FormatDetails at least optionally, and possibly sizing input
  // buffer constraints and/or other buffers based on that.

  QueueInputItem(CodecInputItem::FormatDetails(per_stream_override_format_details));
}

void CodecAdapterH264::CoreCodecQueueInputPacket(CodecPacket* packet) {
  QueueInputItem(CodecInputItem::Packet(packet));
}

void CodecAdapterH264::CoreCodecQueueInputEndOfStream() {
  // This queues a marker, but doesn't force the HW to necessarily decode all
  // the way up to the marker, depending on whether the client closes the stream
  // or switches to a different stream first - in those cases it's fine for the
  // marker to never show up as output EndOfStream.

  {  // scope lock
    std::lock_guard<std::mutex> lock(lock_);
    is_input_end_of_stream_queued_ = true;
  }  // ~lock

  QueueInputItem(CodecInputItem::EndOfStream());
}

// TODO(dustingreen): See comment on CoreCodecStartStream() re. not deleting
// creating as much stuff for each stream.
void CodecAdapterH264::CoreCodecStopStream() {
  {  // scope lock
    std::unique_lock<std::mutex> lock(lock_);

    // This helps any previously-queued ProcessInput() calls return faster, and
    // is checked before calling WaitForParsingCompleted() in case
    // TryStartCancelParsing() does nothing.
    is_cancelling_input_processing_ = true;
  }

  output_sink_->StopAllWaits();

  {  // scope lock
    std::unique_lock<std::mutex> lock(lock_);
    std::condition_variable stop_input_processing_condition;
    // We know there won't be any new queuing of input, so once this posted work
    // runs, we know all previously-queued ProcessInput() calls have returned.
    PostToInputProcessingThread([this, &stop_input_processing_condition] {
      std::list<CodecInputItem> leftover_input_items;
      {  // scope lock
        std::lock_guard<std::mutex> lock(lock_);
        ZX_DEBUG_ASSERT(is_cancelling_input_processing_);
        leftover_input_items = std::move(input_queue_);
        is_cancelling_input_processing_ = false;
      }  // ~lock
      for (auto& input_item : leftover_input_items) {
        if (input_item.is_packet()) {
          events_->onCoreCodecInputPacketDone(input_item.packet());
        }
      }
      stop_input_processing_condition.notify_all();
    });
    while (is_cancelling_input_processing_) {
      stop_input_processing_condition.wait(lock);
    }
    ZX_DEBUG_ASSERT(!is_cancelling_input_processing_);
  }  // ~lock

  // Stop processing queued frames.
  device_->StopEncoder();
}

void CodecAdapterH264::CoreCodecAddBuffer(CodecPort port, const CodecBuffer* buffer) {
  if (port == kInputPort) {
    const char* kInputBufferName = "H264InputBuffer";
    buffer->vmo().set_property(ZX_PROP_NAME, kInputBufferName, strlen(kInputBufferName));
  } else if (port == kOutputPort) {
    const char* kOutputBufferName = "H264OutputBuffer";
    buffer->vmo().set_property(ZX_PROP_NAME, kOutputBufferName, strlen(kOutputBufferName));
    staged_buffers_.Push(buffer);
  }
}

void CodecAdapterH264::CoreCodecConfigureBuffers(
    CodecPort port, const std::vector<std::unique_ptr<CodecPacket>>& packets) {}

void CodecAdapterH264::CoreCodecRecycleOutputPacket(CodecPacket* packet) {
  output_sink_->AddOutputPacket(packet);
}

void CodecAdapterH264::CoreCodecEnsureBuffersNotConfigured(CodecPort port) {
  std::lock_guard<std::mutex> lock(lock_);

  // This adapter should ensure that zero old CodecPacket* or CodecBuffer*
  // remain in this adapter (or below).

  if (port == kInputPort) {
    // There shouldn't be any queued input at this point, but if there is any,
    // fail here even in a release build.
    ZX_ASSERT(input_queue_.empty());
  } else {
    ZX_DEBUG_ASSERT(port == kOutputPort);
    output_sink_->Reset();
  }
}

std::unique_ptr<const fuchsia::media::StreamBufferConstraints>
CodecAdapterH264::CoreCodecBuildNewInputConstraints() {
  auto constraints = std::make_unique<fuchsia::media::StreamBufferConstraints>();

  constraints->set_buffer_constraints_version_ordinal(kInputBufferConstraintsVersionOrdinal);

  constraints->mutable_default_settings()
      ->set_buffer_lifetime_ordinal(0)
      .set_buffer_constraints_version_ordinal(kInputDefaultBufferConstraintsVersionOrdinal)
      .set_packet_count_for_server(kInputDefaultPacketCountForServer)
      .set_packet_count_for_client(kInputDefaultPacketCountForClient)
      .set_per_packet_buffer_bytes(kInputDefaultPerPacketBufferBytes)
      .set_single_buffer_mode(kInputDefaultSingleBufferMode);

  constraints->set_per_packet_buffer_bytes_min(kInputPerPacketBufferBytesMin)
      .set_per_packet_buffer_bytes_recommended(kInputPerPacketBufferBytesRecommended)
      .set_per_packet_buffer_bytes_max(kInputPerPacketBufferBytesMax)
      .set_packet_count_for_server_min(kInputPacketCountForServerMin)
      .set_packet_count_for_server_recommended(kInputPacketCountForServerRecommended)
      .set_packet_count_for_server_recommended_max(kInputPacketCountForServerRecommendedMax)
      .set_packet_count_for_server_max(kInputPacketCountForServerMax)
      .set_packet_count_for_client_min(kInputPacketCountForClientMin)
      .set_packet_count_for_client_max(kInputPacketCountForClientMax)
      .set_single_buffer_mode_allowed(kInputSingleBufferModeAllowed)
      .set_is_physically_contiguous_required(true);

  return constraints;
}

std::unique_ptr<const fuchsia::media::StreamOutputConstraints>
CodecAdapterH264::CoreCodecBuildNewOutputConstraints(
    uint64_t stream_lifetime_ordinal, uint64_t new_output_buffer_constraints_version_ordinal,
    bool buffer_constraints_action_required) {
  // sysmem constraints take priority over StreamOutputConstraints so just use some defaults that
  // pass checks here
  constexpr uint32_t kDefaultPacketCountForClient = 1;
  constexpr uint32_t kDefaultPacketCountForServer = 1;
  constexpr uint32_t kRecommendedMaxPacketCount = std::numeric_limits<uint32_t>::max();
  constexpr uint32_t kServerMaxPacketCount = std::numeric_limits<uint32_t>::max();
  constexpr uint32_t kClientMaxPacketCount = std::numeric_limits<uint32_t>::max();

  std::unique_ptr<fuchsia::media::StreamOutputConstraints> config =
      std::make_unique<fuchsia::media::StreamOutputConstraints>();

  config->set_stream_lifetime_ordinal(stream_lifetime_ordinal);

  auto* constraints = config->mutable_buffer_constraints();
  auto* default_settings = constraints->mutable_default_settings();

  // For the moment, there will be only one StreamOutputConstraints, and it'll
  // need output buffers configured for it.
  ZX_DEBUG_ASSERT(buffer_constraints_action_required);
  config->set_buffer_constraints_action_required(buffer_constraints_action_required);
  constraints->set_buffer_constraints_version_ordinal(
      new_output_buffer_constraints_version_ordinal);

  // 0 is intentionally invalid - the client must fill out this field.
  default_settings->set_buffer_lifetime_ordinal(0)
      .set_buffer_constraints_version_ordinal(new_output_buffer_constraints_version_ordinal)
      .set_packet_count_for_server(kDefaultPacketCountForServer)
      .set_packet_count_for_client(kDefaultPacketCountForClient)
      .set_per_packet_buffer_bytes(kOutputBufferMinSizeBytes)
      .set_single_buffer_mode(false);

  // For the moment, let's tell the client to allocate this exact size.
  constraints->set_per_packet_buffer_bytes_min(kOutputBufferMinSizeBytes)
      .set_per_packet_buffer_bytes_recommended(kOutputBufferMinSizeBytes)
      .set_per_packet_buffer_bytes_max(kOutputBufferMaxSizeBytes)
      .set_packet_count_for_server_min(kDefaultPacketCountForServer)
      .set_packet_count_for_server_recommended(kDefaultPacketCountForServer)
      .set_packet_count_for_server_recommended_max(kRecommendedMaxPacketCount)
      .set_packet_count_for_server_max(kServerMaxPacketCount)
      .set_packet_count_for_client_min(0)
      .set_packet_count_for_client_max(kClientMaxPacketCount);

  // False because it's not required and not encouraged for a video encoder
  // output to allow single buffer mode.
  constraints->set_single_buffer_mode_allowed(false);

  constraints->set_is_physically_contiguous_required(true);

  return config;
}

fuchsia::sysmem::BufferCollectionConstraints
CodecAdapterH264::CoreCodecGetBufferCollectionConstraints(
    CodecPort port, const fuchsia::media::StreamBufferConstraints& stream_buffer_constraints,
    const fuchsia::media::StreamBufferPartialSettings& partial_settings) {
  fuchsia::sysmem::BufferCollectionConstraints result;

  // For now, we didn't report support for single_buffer_mode, and CodecImpl
  // will have failed the codec already by this point if the client tried to
  // use single_buffer_mode.
  //
  // TODO(dustingreen): Support single_buffer_mode on input (only).
  ZX_DEBUG_ASSERT(!partial_settings.has_single_buffer_mode() ||
                  !partial_settings.single_buffer_mode());
  // The CodecImpl won't hand us the sysmem token, so we shouldn't expect to
  // have the token here.
  ZX_DEBUG_ASSERT(!partial_settings.has_sysmem_token());

  if (port == kInputPort) {
    result.min_buffer_count_for_camping = kInputMinBufferCountForCamping;
    result.max_buffer_count = kInputMaxBufferCount;
  } else {
    result.min_buffer_count_for_camping = kOutputMinBufferCountForCamping;
    result.max_buffer_count = kOutputMaxBufferCount;
  }

  uint32_t per_packet_buffer_bytes_min;
  uint32_t per_packet_buffer_bytes_max;
  if (port == kOutputPort) {
    per_packet_buffer_bytes_min = kOutputBufferMinSizeBytes;
    per_packet_buffer_bytes_max = kOutputBufferMaxSizeBytes;
  } else {
    ZX_DEBUG_ASSERT(port == kInputPort);
    // NV12, based on min stride.
    per_packet_buffer_bytes_min = min_stride_ * height_ * 3 / 2;
    per_packet_buffer_bytes_max = 0xFFFFFFFF;
  }

  result.has_buffer_memory_constraints = true;
  result.buffer_memory_constraints.min_size_bytes = per_packet_buffer_bytes_min;
  result.buffer_memory_constraints.max_size_bytes = per_packet_buffer_bytes_max;
  // amlogic requires physically contiguous on both input and output
  result.buffer_memory_constraints.physically_contiguous_required = true;
  result.buffer_memory_constraints.secure_required = false;
  result.buffer_memory_constraints.cpu_domain_supported = true;
  result.buffer_memory_constraints.ram_domain_supported = true;
  result.buffer_memory_constraints
      .heap_permitted[result.buffer_memory_constraints.heap_permitted_count++] =
      fuchsia::sysmem::HeapType::SYSTEM_RAM;

  if (port == kInputPort) {
    result.image_format_constraints_count = 1;
    fuchsia::sysmem::ImageFormatConstraints& image_constraints = result.image_format_constraints[0];
    image_constraints.pixel_format.type = fuchsia::sysmem::PixelFormatType::NV12;
    image_constraints.pixel_format.has_format_modifier = true;
    image_constraints.pixel_format.format_modifier.value = fuchsia::sysmem::FORMAT_MODIFIER_LINEAR;
    // TODO(MTWN-251): confirm that REC709 is always what we want here, or plumb
    // actual YUV color space if it can ever be REC601_*.  Since 2020 and 2100
    // are minimum 10 bits per Y sample and we're outputting NV12, 601 is the
    // only other potential possibility here.
    image_constraints.color_spaces_count = 1;
    image_constraints.color_space[0].type = fuchsia::sysmem::ColorSpaceType::REC709;

    // The non-"required_" fields indicate the decoder's ability to potentially
    // output frames at various dimensions as coded in the stream.  Aside from
    // the current stream being somewhere in these bounds, these have nothing to
    // do with the current stream in particular.
    image_constraints.min_coded_width = 16;
    image_constraints.max_coded_width = 4096;
    image_constraints.min_coded_height = 16;
    // This intentionally isn't the _height_ of a 4096x2176 frame, it's
    // intentionally the _width_ of a 4096x2176 frame assigned to
    // max_coded_height.
    //
    // See max_coded_width_times_coded_height.  We intentionally constrain the
    // max dimension in width or height to the width of a 4096x2176 frame.
    // While the HW might be able to go bigger than that as long as the other
    // dimension is smaller to compensate, we don't really need to enable any
    // larger than 4096x2176's width in either dimension, so we don't.
    image_constraints.max_coded_height = 4096;
    image_constraints.min_bytes_per_row = 16;
    // no hard-coded max stride, at least for now
    image_constraints.max_bytes_per_row = 0xFFFFFFFF;
    image_constraints.max_coded_width_times_coded_height = 4096 * 2176;
    image_constraints.layers = 1;
    image_constraints.coded_width_divisor = 16;
    image_constraints.coded_height_divisor = 16;
    image_constraints.bytes_per_row_divisor = 16;
    // TODO(dustingreen): Since this is a producer that will always produce at
    // offset 0 of a physical page, we don't really care if this field is
    // consistent with any constraints re. what the HW can do.
    image_constraints.start_offset_divisor = 1;
    // Odd display dimensions are permitted, but these don't imply odd NV12
    // dimensions - those are constrainted by coded_width_divisor and
    // coded_height_divisor which are both 16.
    image_constraints.display_width_divisor = 1;
    image_constraints.display_height_divisor = 1;

    // The decoder is producing frames and the decoder has no choice but to
    // produce frames at their coded size.  The decoder wants to potentially be
    // able to support a stream with dynamic resolution, potentially including
    // dimensions both less than and greater than the dimensions that led to the
    // current need to allocate a BufferCollection.  For this reason, the
    // required_ fields are set to the exact current dimensions, and the
    // permitted (non-required_) fields is set to the full potential range that
    // the decoder could potentially output.  If an initiator wants to require a
    // larger range of dimensions that includes the required range indicated
    // here (via a-priori knowledge of the potential stream dimensions), an
    // initiator is free to do so.
    image_constraints.required_min_coded_width = width_;
    image_constraints.required_max_coded_width = width_;
    image_constraints.required_min_coded_height = height_;
    image_constraints.required_max_coded_height = height_;
  } else {
    ZX_DEBUG_ASSERT(result.image_format_constraints_count == 0);
  }

  // We don't have to fill out usage - CodecImpl takes care of that.
  ZX_DEBUG_ASSERT(!result.usage.cpu);
  ZX_DEBUG_ASSERT(!result.usage.display);
  ZX_DEBUG_ASSERT(!result.usage.vulkan);
  ZX_DEBUG_ASSERT(!result.usage.video);

  return result;
}

void CodecAdapterH264::CoreCodecSetBufferCollectionInfo(
    CodecPort port, const fuchsia::sysmem::BufferCollectionInfo_2& buffer_collection_info) {
  ZX_DEBUG_ASSERT(buffer_collection_info.settings.buffer_settings.is_physically_contiguous);
  if (port == kInputPort) {
    ZX_DEBUG_ASSERT(buffer_collection_info.settings.has_image_format_constraints);
    ZX_DEBUG_ASSERT(buffer_collection_info.settings.image_format_constraints.pixel_format.type ==
                    fuchsia::sysmem::PixelFormatType::NV12);
  }
}

fuchsia::media::StreamOutputFormat CodecAdapterH264::CoreCodecGetOutputFormat(
    uint64_t stream_lifetime_ordinal, uint64_t new_output_format_details_version_ordinal) {
  fuchsia::media::StreamOutputFormat result;
  result.set_stream_lifetime_ordinal(stream_lifetime_ordinal);
  result.mutable_format_details()->set_format_details_version_ordinal(
      new_output_format_details_version_ordinal);

  result.mutable_format_details()->set_mime_type("video/h264");

  fuchsia::media::VideoFormat video_format;

  auto compressed_format = fuchsia::media::VideoCompressedFormat();
  compressed_format.set_temp_field_todo_remove(0);
  video_format.set_compressed(std::move(compressed_format));

  result.mutable_format_details()->mutable_domain()->set_video(std::move(video_format));

  return result;
}

void CodecAdapterH264::CoreCodecMidStreamOutputBufferReConfigPrepare() {}

void CodecAdapterH264::CoreCodecMidStreamOutputBufferReConfigFinish() {
  std::optional<const CodecBuffer*> staged_buffer;
  while ((staged_buffer = staged_buffers_.Pop())) {
    output_sink_->AddOutputBuffer(*staged_buffer);
  }
}

void CodecAdapterH264::CoreCodecSetSecureMemoryMode(
    CodecPort port, fuchsia::mediacodec::SecureMemoryMode secure_memory_mode) {}

void CodecAdapterH264::PostSerial(async_dispatcher_t* dispatcher, fit::closure to_run) {
  zx_status_t post_result = async::PostTask(dispatcher, std::move(to_run));
  ZX_ASSERT_MSG(post_result == ZX_OK, "async::PostTask() failed - result: %d\n", post_result);
}

void CodecAdapterH264::PostToInputProcessingThread(fit::closure to_run) {
  PostSerial(input_processing_loop_.dispatcher(), std::move(to_run));
}

void CodecAdapterH264::QueueInputItem(CodecInputItem input_item) {
  bool is_trigger_needed = false;
  {  // scope lock
    std::lock_guard<std::mutex> lock(lock_);
    // For now we don't worry about avoiding a trigger if we happen to queue
    // when ProcessInput() has removed the last item but ProcessInput() is still
    // running.
    if (!is_process_input_queued_) {
      is_trigger_needed = input_queue_.empty();
      is_process_input_queued_ = is_trigger_needed;
    }
    input_queue_.emplace_back(std::move(input_item));
  }  // ~lock
  if (is_trigger_needed) {
    PostToInputProcessingThread(fit::bind_member(this, &CodecAdapterH264::ProcessInput));
  }
}

CodecInputItem CodecAdapterH264::DequeueInputItem() {
  {  // scope lock
    std::lock_guard<std::mutex> lock(lock_);
    if (is_stream_failed_ || is_cancelling_input_processing_ || input_queue_.empty()) {
      return CodecInputItem::Invalid();
    }
    CodecInputItem to_ret = std::move(input_queue_.front());
    input_queue_.pop_front();
    return to_ret;
  }  // ~lock
}

void CodecAdapterH264::ProcessInput() {
  {  // scope lock
    std::lock_guard<std::mutex> lock(lock_);
    is_process_input_queued_ = false;
  }  // ~lock

  auto status = device_->EnsureFwLoaded();
  if (status != ZX_OK) {
    events_->onCoreCodecFailCodec("failed to init hw");
    return;
  }

  while (true) {
    CodecInputItem item = DequeueInputItem();

    if (!item.is_valid()) {
      // input loop should exit
      return;
    }

    if (item.is_format_details()) {
      status = device_->UpdateEncoderSettings(item.format_details());
      if (status != ZX_OK) {
        events_->onCoreCodecFailCodec("failed update encoder settings");
        return;
      }

      if (output_sink_->OutputBufferCount() < kOutputMinBufferCountForCamping) {
        // Currently, this will only run if output buffers aren't presently configured.
        // TODO(afoxley) In future, new encode params may imply a need to re-configure
        // output buffers that are already configured but too small or too few in number
        // for higher output bitrate.
        events_->onCoreCodecMidStreamOutputConstraintsChange(
            /*output_re_config_required=*/true);
      }
      continue;
    }

    if (item.is_end_of_stream()) {
      // TODO(afoxley) possibly redundant with Flush at end of function
      output_sink_->Flush();
      events_->onCoreCodecOutputEndOfStream(/*error_detected_before=*/false);
      continue;
    }

    auto return_packet =
        fit::defer([this, &item] { events_->onCoreCodecInputPacketDone(item.packet()); });

    // errors are logged and handled closer to source in callback
    //
    // TODO(afoxley) We may need to have the hardware encode into a large-ish output buffer then
    // break it up into smaller sub-NAL chunks for sending to output. This means adjusting the
    // output chunk size passed in here.
    (void)output_sink_->NextOutputBlock(
        kOutputBufferMinSizeBytes, std::nullopt,
        [this,
         &item](OutputSink::OutputBlock output_block) -> std::pair<size_t, OutputSink::UserStatus> {
          if (device_->SetInputBuffer(item.packet()->buffer()) != ZX_OK) {
            events_->onCoreCodecFailCodec("Failed to setup input buffer");
            return {0, OutputSink::kError};
          }

          // input frames are expected to start at buffer offset 0
          if (item.packet()->start_offset()) {
            events_->onCoreCodecFailCodec("Input has offset");
            return {0, OutputSink::kError};
          }

          device_->SetOutputBuffer(output_block.buffer);
          uint32_t output_len = 0;
          auto status = device_->EncodeFrame(&output_len);

          if (status != ZX_OK) {
            ENCODE_ERROR("Encoding failed: %d", status);
            events_->onCoreCodecFailCodec("Encoding failed: %d", status);
            // TODO(afoxley) soft reset?
            return {0, OutputSink::kError};
          }

          return {output_len, OutputSink::kSuccess};
        });

    // force one packet per buffer
    output_sink_->Flush();
  }
}

void CodecAdapterH264::OnCoreCodecFailStream(fuchsia::media::StreamError error) {
  {  // scope lock
    std::lock_guard<std::mutex> lock(lock_);
    is_stream_failed_ = true;
  }
  events_->onCoreCodecFailStream(error);
}
