// 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 "lib/media/test/codec_client.h"

#include <lib/async/cpp/task.h>
#include <lib/media/test/one_shot_event.h>
#include <lib/syslog/cpp/macros.h>

#include <algorithm>
#include <chrono>
#include <iostream>
#include <random>

#include "src/lib/fsl/handles/object_info.h"

namespace {

// The client would like there to be at least this many input buffers.  Despite
// the client filling input buffers quickly, it's still non-zero duration, so
// using 1 here can help avoid short stalls while an input buffer is being
// filled.
constexpr uint32_t kMinInputBufferCountForCamping = 1;
// The client intends to hold onto this many output buffers for a non-transient
// duration.
constexpr uint32_t kMinOutputBufferCountForCamping = 1;

// For input, this example doesn't re-configure input buffers, so there's only
// one buffer_lifetime_ordinal.
constexpr uint64_t kInputBufferLifetimeOrdinal = 1;

// It's fine to increase this threshold if we add a new usage of CodecClient
// with new StreamProcessor server that should/must have more buffers.  This is
// here to check that we're not allocating more output buffers than expected.
// If the various cases get further apart, it'd probably be worthwhile to plumb
// per-case from code that's using CodecClient.  For now this is based on what
// use_h264_decoder_test allocates (max across astro and QEMU).
//
// This is basically 16 max DPB for h264, 1 to decode into (assumed separate
// from DPB for now), and 1 for the client.
constexpr uint32_t kMaxExpectedBufferCount = 18;

}  // namespace

CodecClient::CodecClient(async::Loop* loop, thrd_t loop_thread,
                         fuchsia::sysmem::AllocatorHandle sysmem)
    : loop_(loop), dispatcher_(loop_->dispatcher()), loop_thread_(loop_thread) {
  // Only one request is ever created, so we create it in the constructor to
  // avoid needing any manual enforcement that we only do this once.
  fuchsia::media::StreamProcessorHandle codec_handle;
  temp_codec_request_ = codec_handle.NewRequest();

  // Bind sysmem_ using FIDL thread.  This is ok because all communication with
  // sysmem also happens via FIDL thread so will queue after this posted lambda.
  PostToFidlThread([this, sysmem = std::move(sysmem),
                    codec_handle = std::move(codec_handle)]() mutable {
    zx_status_t bind_status = sysmem_.Bind(std::move(sysmem), dispatcher_);
    ZX_ASSERT(bind_status == ZX_OK);
    sysmem_.set_error_handler(
        [](zx_status_t status) { FX_PLOGS(FATAL, status) << "sysmem_ failed - unexpected"; });
    sysmem_->SetDebugClientInfo(fsl::GetCurrentProcessName(), fsl::GetCurrentProcessKoid());

    codec_ = codec_handle.Bind();
    codec_->EnableOnStreamFailed();
    // We want the error handler set up before any error can possibly be generated
    // by the channel so there's no chance of missing an error.  The async::Loop
    // that we'll use is already running separately from the current thread.
    codec_.set_error_handler([this](zx_status_t status) {
      // Obviously a non-example client that continues to have a purpose even if
      // one of its codecs dies would want to handle errors in a more contained
      // way.
      //
      // TODO(dustingreen): get and print epitaph once that's possible.
      if (!in_lax_mode_) {
        ZX_PANIC("codec_ failed - !in_lax_mode_\n");
      } else {
        FX_PLOGS(WARNING, status) << "codec_ failed - in_lax_mode_";
        connection_lost_ = true;
        output_pending_condition_.notify_all();
        is_sync_complete_condition_.notify_all();
        input_free_packet_list_not_empty_.notify_all();
      }
    });

    // We treat event setup as much as possible like a hidden part of creating the
    // CodecPtr.  If NewBinding() has !is_valid(), we rely on the Codec server to
    // close the Codec channel async.
    codec_.events().OnStreamFailed = fit::bind_member<&CodecClient::OnStreamFailed>(this);
    codec_.events().OnInputConstraints = fit::bind_member<&CodecClient::OnInputConstraints>(this);
    codec_.events().OnFreeInputPacket = fit::bind_member<&CodecClient::OnFreeInputPacket>(this);
    codec_.events().OnOutputConstraints = fit::bind_member<&CodecClient::OnOutputConstraints>(this);
    codec_.events().OnOutputFormat = fit::bind_member<&CodecClient::OnOutputFormat>(this);
    codec_.events().OnOutputPacket = fit::bind_member<&CodecClient::OnOutputPacket>(this);
    codec_.events().OnOutputEndOfStream = fit::bind_member<&CodecClient::OnOutputEndOfStream>(this);
  });
}

CodecClient::~CodecClient() { Stop(); }

fidl::InterfaceRequest<fuchsia::media::StreamProcessor> CodecClient::GetTheRequestOnce() {
  ZX_DEBUG_ASSERT(!is_start_called_);
  return std::move(temp_codec_request_);
}

void CodecClient::SetMinInputBufferSize(uint32_t min_input_buffer_size) {
  ZX_DEBUG_ASSERT(!is_start_called_);
  min_input_buffer_size_ = min_input_buffer_size;
}

void CodecClient::SetMinOutputBufferSize(uint32_t min_output_buffer_size) {
  ZX_DEBUG_ASSERT(!is_start_called_);
  min_output_buffer_size_ = min_output_buffer_size;
}

void CodecClient::SetMinOutputBufferCount(uint32_t min_output_buffer_count) {
  ZX_DEBUG_ASSERT(!is_start_called_);
  min_output_buffer_count_ = min_output_buffer_count;
}

void CodecClient::Start() {
  ZX_DEBUG_ASSERT(!is_start_called_);
  is_start_called_ = true;
  // The caller is responsible for calling this method only once, using the main
  // thread.  This method only holds the lock for short periods, and has to
  // release the lock many times during this method, which is reasonable given
  // the nature of this method as an overall state progression sequencer.

  // Call Sync() and wait for it's response _only_ to force the Codec server to
  // reach the point of being able response to messages, just for easier
  // debugging if just starting the Codec server fails instead.  Actual clients
  // don't need to use Sync() here.
  CallSyncAndWaitForResponse();
  FX_VLOGS(3) << "Sync() completed, which means the Codec server exists.";
  if (connection_lost_)
    return;

  FX_VLOGS(3) << "Waiting for OnInputConstraints() from the Codec server...";
  // The Codec client can rely on an OnInputConstraints() arriving shortly,
  // without any message required from the client first.  The
  // OnInputConstraints() may in future actually be sent by the CodecFactory,
  // but it'll still be sent to the client on the Codec channel in any case.
  {  // scope lock
    std::unique_lock<std::mutex> lock(lock_);
    // In this example we're not paying attention to channel failure here
    // because channel failure calls exit().
    while (!input_constraints_) {
      input_constraints_exist_condition_.wait(lock);
    }
  }  // ~lock
  ZX_ASSERT(input_constraints_);
  FX_VLOGS(3) << "Got OnInputConstraints() from the Codec server.";

  // We know input_constraints_ won't change outside the lock because we prevent
  // that in OnInputConstraints() by only accepting input constraints if there
  // aren't already input constraints.

  // Now that we have input constraints, we can create all the input buffers and
  // tell the Codec server about them.  We tell the Codec server by using
  // SetInputSettings() followed by one or num_buffers calls to
  // AddInputBuffer().  These are necessary before it becomes permissible to
  // call CreateStream().
  //
  // We're not on the FIDL thread, so we need to async::PostTask() over to the
  // FIDL thread to send any FIDL message.

  uint32_t input_packet_count;
  fuchsia::sysmem::BufferCollectionInfo_2 buffer_collection_info;
  if (!ConfigurePortBufferCollection(false, kInputBufferLifetimeOrdinal,
                                     input_constraints_->buffer_constraints_version_ordinal(),
                                     &input_packet_count, &input_buffer_collection_,
                                     &buffer_collection_info)) {
    FX_LOGS(FATAL) << "ConfigurePortBufferCollection failed (input)";
  }

  ZX_ASSERT(input_free_packet_bits_.empty());
  input_free_packet_bits_.resize(input_packet_count, true);
  all_input_buffers_.reserve(buffer_collection_info.buffer_count);
  for (uint32_t i = 0; i < buffer_collection_info.buffer_count; i++) {
    std::unique_ptr<CodecBuffer> local_buffer = CodecBuffer::CreateFromVmo(
        i, std::move(buffer_collection_info.buffers[i].vmo),
        static_cast<uint32_t>(buffer_collection_info.buffers[i].vmo_usable_start),
        buffer_collection_info.settings.buffer_settings.size_bytes, true,
        buffer_collection_info.settings.buffer_settings.is_physically_contiguous);
    if (!local_buffer) {
      FX_LOGS(FATAL) << "CodecBuffer::CreateFromVmo() failed";
    }
    ZX_ASSERT(all_input_buffers_.size() == i);
    all_input_buffers_.push_back(std::move(local_buffer));
  }

  // Now that we've SetInputBufferPartialSettings(), the codec will get the
  // input buffers from sysmem.  The input packets all start as free with the
  // Codec client, per protocol.  Same goes for input buffers - this client
  // happens to track in terms of packets and have buffer_index == packet_index.
  //
  // TODO(dustingreen): Have CodecClient scramble the order of packets vs.
  // buffers to check that CodecImpl is handling that correctly for input
  // packets.
  input_free_packet_list_.reserve(input_packet_count);
  for (uint32_t i = 0; i < input_packet_count; i++) {
    input_free_packet_list_.push_back(i);
  }
  input_packet_index_to_buffer_index_.resize(input_packet_count);
  input_free_buffer_list_.reserve(buffer_collection_info.buffer_count);
  for (uint32_t i = 0; i < buffer_collection_info.buffer_count; ++i) {
    input_free_buffer_list_.push_back(i);
  }

  // Shuffle both free lists, so that we'll notice if a StreamProcessor server has inappropriate
  // dependency on ordering of either list or any particular association of packet_index with
  // buffer_index.
  std::random_device random_device;
  std::mt19937 prng(random_device());
  std::shuffle(input_free_packet_list_.begin(), input_free_packet_list_.end(), prng);
  std::shuffle(input_free_buffer_list_.begin(), input_free_buffer_list_.end(), prng);
}

bool CodecClient::CreateAndSyncBufferCollection(
    fuchsia::sysmem::BufferCollectionSyncPtr* out_buffer_collection,
    fidl::InterfaceHandle<fuchsia::sysmem::BufferCollectionToken>* out_codec_sysmem_token) {
  fuchsia::sysmem::BufferCollectionSyncPtr buffer_collection;
  fidl::InterfaceHandle<fuchsia::sysmem::BufferCollectionToken> codec_sysmem_token;

  // Create client_token which will get converted into out_buffer_collection.
  fuchsia::sysmem::BufferCollectionTokenSyncPtr client_token;
  fidl::InterfaceRequest<fuchsia::sysmem::BufferCollectionToken> client_token_request =
      client_token.NewRequest();

  // Create codec_sysmem_token that'll get returned via out_codec_sysmem_token.
  client_token->Duplicate(std::numeric_limits<uint32_t>::max(), codec_sysmem_token.NewRequest());

  // client_token gets converted into a buffer_collection.
  //
  // Start client_token connection and start converting it into a
  // BufferCollection, so we can Sync() the previous Duplicate().
  PostToFidlThread([this, client_token_request = std::move(client_token_request),
                    client_token = client_token.Unbind(),
                    buffer_collection_request = buffer_collection.NewRequest()]() mutable {
    if (!sysmem_) {
      return;
    }
    sysmem_->AllocateSharedCollection(std::move(client_token_request));
    // codec_sysmem_token will be known to sysmem by the time client_token
    // closure is seen by sysmem, which in turn is before
    // buffer_collection_request will be hooked up, which is why
    // buffer_collection->Sync() completion below is enough to prove that
    // sysmem knows about codec_sysmem_token before codec_sysmem_token is
    // sent to the codec.
    sysmem_->BindSharedCollection(std::move(client_token), std::move(buffer_collection_request));
  });

  // After Sync() completes its round trip, we know that sysmem knows about
  // codec_sysmem_token (causally), which is important because we'll shortly
  // send codec_sysmem_token to the codec which will use codec_sysmem_token via
  // a different sysmem channel.
  zx_status_t sync_status = buffer_collection->Sync();
  if (sync_status != ZX_OK) {
    FX_PLOGS(FATAL, sync_status) << "buffer_collection->Sync() failed";
  }

  *out_buffer_collection = std::move(buffer_collection);
  *out_codec_sysmem_token = std::move(codec_sysmem_token);
  return true;
}

bool CodecClient::WaitForSysmemBuffersAllocated(
    bool is_output, fuchsia::sysmem::BufferCollectionSyncPtr* buffer_collection_param,
    fuchsia::sysmem::BufferCollectionInfo_2* out_buffer_collection_info) {
  // The style guide doesn't like non-const &, but the code in this method is
  // easier to read with a non-const &, so treat it that way within this method.
  fuchsia::sysmem::BufferCollectionSyncPtr& buffer_collection = *buffer_collection_param;
  fuchsia::sysmem::BufferCollectionInfo_2 result_buffer_collection_info;

  // It's not permitted to send input data until the client knows that sysmem
  // is done allocating.  It's not required that the client know that the
  // codec knows that sysmem is done allocating though - the server will
  // verify that sysmem is done by communicating with sysmem directly as
  // needed.
  zx_status_t allocate_status;
  zx_status_t call_status =
      buffer_collection->WaitForBuffersAllocated(&allocate_status, &result_buffer_collection_info);
  if (call_status != ZX_OK) {
    FX_PLOGS(ERROR, call_status) << "WaitForBuffersAllocated returned failure";
    return false;
  }
  if (allocate_status != ZX_OK) {
    FX_PLOGS(ERROR, allocate_status) << "WaitForBuffersAllocated allocation failed";
    return false;
  }

  // This is a little noisy, but it can be useful to see how many buffers are being used.  Make sure
  // it doesn't show up on stderr though.
  std::cout << "WaitForSysmemBuffersAllocated() done - is_output: " << is_output
            << " buffer_count: " << result_buffer_collection_info.buffer_count << std::endl;

  *out_buffer_collection_info = std::move(result_buffer_collection_info);
  return true;
}

void CodecClient::Stop() {
  ZX_DEBUG_ASSERT(thrd_current() != loop_thread_);
  OneShotEvent unbind_and_loop_lambdas_done;
  PostToFidlThread([this, &unbind_and_loop_lambdas_done] {
    codec_ = nullptr;
    sysmem_ = nullptr;
    input_buffer_collection_ = nullptr;
    output_buffer_collection_ = nullptr;

    // Any lambdas previously queued (by any handlers for the bindings we're
    // unbinding just above) need to be done also, so fence those by re-posting.
    //
    // This relies on lambdas on fidl thread (other than this one) to not
    // re-post to the fidl thread, which we enforce for all calls to
    // PostToFidlThread() except this one.
    PostToFidlThread([&unbind_and_loop_lambdas_done] { unbind_and_loop_lambdas_done.Signal(); },
                     false);
  });
  unbind_and_loop_lambdas_done.Wait();
}

void CodecClient::DoNotQueueInputPacketAfterAll(std::unique_ptr<fuchsia::media::Packet> packet) {
  ZX_ASSERT(packet->has_header());
  ZX_ASSERT(packet->header().has_buffer_lifetime_ordinal());
  ZX_ASSERT(packet->header().has_packet_index());
  ZX_ASSERT(packet->has_buffer_index());
  ZX_ASSERT(packet->has_stream_lifetime_ordinal());
  ZX_ASSERT(packet->has_start_offset());
  ZX_ASSERT(packet->has_valid_length_bytes());
  // timestamp_ish field is optional start_access_unit field is optional
  // known_end_access_unit is optional
  {  // scope lock
    // This packet is already not on the free list, but is still considered free
    // from a protocol point of view, so update that part.
    std::unique_lock<std::mutex> lock(lock_);
    ZX_ASSERT(input_free_packet_bits_[packet->header().packet_index()]);
    input_free_packet_bits_[packet->header().packet_index()] = false;
    // From here it's as if this packet is already in flight with the server.
  }  // ~lock
  async::PostTask(dispatcher_, [this, packet = std::move(packet)]() mutable {
    // Instead of codec_->QueueInputPacket().
    OnFreeInputPacket(std::move(*packet->mutable_header()));
    // ~packet
  });
}

void CodecClient::PostToFidlThread(fit::closure to_run, bool enforce_no_re_posting) {
  ZX_DEBUG_ASSERT(thrd_current() != loop_thread_ || !enforce_no_re_posting);
  zx_status_t post_status = async::PostTask(dispatcher_, std::move(to_run));
  ZX_ASSERT(post_status == ZX_OK);
}

void CodecClient::CallSyncAndWaitForResponse() {
  // |is_sync_complete_condition_| may also be signaled on connection lost, so it
  // needs to be an instance variable.
  bool is_sync_complete = false;
  // Capturing stuff with just "&" is sometimes frowned upon, but in this case
  // there's no chance of any lambda outliving anything, so it's fine.  The
  // outer lambda is because ProxyController isn't thread-safe and the present
  // method is called from the main thread not the FIDL thread, so we have to
  // switch threads to send a FIDL message.  The inner lambda is the completion
  // callback.
  FX_VLOGS(3) << "before calling Sync() (main thread)...";
  async::PostTask(dispatcher_, [&] {
    FX_VLOGS(3) << "before calling Sync() (fidl thread)...";
    codec_->Sync([&]() {
      {  // scope lock
        std::unique_lock<std::mutex> lock(is_sync_complete_lock_);
        is_sync_complete = true;
      }  // ~lock
      is_sync_complete_condition_.notify_all();
    });
  });
  FX_VLOGS(3) << "after calling Sync() - waiting...\n";
  {  // scope lock
    std::unique_lock<std::mutex> lock(is_sync_complete_lock_);
    // We rely on the channel error handler to be doing an exit() for this loop
    // to be reasonable without checking for channel failure here.
    while (!is_sync_complete && !connection_lost_) {
      is_sync_complete_condition_.wait(lock);
    }
  }
  FX_VLOGS(3) << "after calling Sync() - done waiting\n";
  ZX_ASSERT(is_sync_complete || connection_lost_);
}

void CodecClient::TrackOutputStreamLifetimeOrdinal(uint64_t output_stream_lifetime_ordinal) {
  // must be odd
  ZX_ASSERT(output_stream_lifetime_ordinal % 2 == 1);
  ZX_ASSERT(output_stream_lifetime_ordinal >= output_stream_lifetime_ordinal_);
  if (output_stream_lifetime_ordinal > output_stream_lifetime_ordinal_) {
    // We're allowed to forget format any time there's a stream change, so we
    // do.  This isn't critical for this test code, but it's closer to how a
    // real client will likely track the output format on a per-stream basis.
    ZX_ASSERT(!last_output_format_ ||
              last_output_format_->stream_lifetime_ordinal() == output_stream_lifetime_ordinal_);
    output_stream_lifetime_ordinal_ = output_stream_lifetime_ordinal;
    last_output_format_ = nullptr;
    // We intentionally don't reset is_packet_since_last_format_.
  }
}

void CodecClient::OnInputConstraints(fuchsia::media::StreamBufferConstraints input_constraints) {
  if (input_constraints_) {
    FX_LOGS(FATAL) << "server sent more than one input constraints";
  }
  {  // scope lock
    std::unique_lock<std::mutex> lock(lock_);
    input_constraints_ =
        std::make_unique<fuchsia::media::StreamBufferConstraints>(std::move(input_constraints));
  }  // ~lock
  input_constraints_exist_condition_.notify_all();
}

void CodecClient::OnFreeInputPacket(fuchsia::media::PacketHeader free_input_packet) {
  bool free_buffer_list_was_empty;
  bool free_packet_list_was_empty;
  {  // scope lock
    std::unique_lock<std::mutex> lock(lock_);
    if (!free_input_packet.has_packet_index()) {
      FX_LOGS(FATAL) << "OnFreeInputPacket(): Packet has no index.";
    }
    if (input_free_packet_bits_[free_input_packet.packet_index()]) {
      // already free - a normal client wouldn't want to just exit here since
      // this is the server's fault - in this example we just care that we
      // detect it
      FX_LOGS(FATAL) << "OnFreeInputPacket() when already free - server's fault? - "
                        "packet_index: "
                     << free_input_packet.packet_index();
    }
    free_buffer_list_was_empty = input_free_buffer_list_.empty();
    input_free_buffer_list_.push_back(
        input_packet_index_to_buffer_index_[free_input_packet.packet_index()]);
    free_packet_list_was_empty = input_free_packet_list_.empty();
    input_free_packet_list_.push_back(free_input_packet.packet_index());
    input_free_packet_bits_[free_input_packet.packet_index()] = true;
  }  // ~lock
  if (free_buffer_list_was_empty) {
    input_free_buffer_list_not_empty_.notify_all();
  }
  if (free_packet_list_was_empty) {
    input_free_packet_list_not_empty_.notify_all();
  }
}

std::unique_ptr<fuchsia::media::Packet> CodecClient::BlockingGetFreeInputPacket() {
  // This should be significantly longer than kWatchdogTimeoutMs in amlogic_decoder watchdog.cc.
  constexpr uint32_t kBlockingGetFreeInputPacketTimeoutMs = 20000;
  auto now = std::chrono::steady_clock::now();
  auto wait_until_time = now + std::chrono::milliseconds(kBlockingGetFreeInputPacketTimeoutMs);
  uint32_t free_packet_index;
  {  // scope lock
    std::unique_lock<std::mutex> lock(lock_);
    while (input_free_packet_list_.empty()) {
      if (connection_lost_)
        return nullptr;
      auto wait_until_result = input_free_packet_list_not_empty_.wait_until(lock, wait_until_time);
      if (wait_until_result == std::cv_status::timeout) {
        ZX_PANIC(
            "BlockingGetFreeInputPacket() no packet available for too long - "
            "kBlockingGetFreeInputPacketTimeoutMs: %u\n",
            kBlockingGetFreeInputPacketTimeoutMs);
        // not reached
        return nullptr;
      }
      ZX_DEBUG_ASSERT(wait_until_result == std::cv_status::no_timeout);
    }
    free_packet_index = input_free_packet_list_.back();
    input_free_packet_list_.pop_back();
    // We intentionally do not modify input_free_packet_bits_ here, as those bits are
    // tracking the protocol level free-ness, so will get updated when the
    // caller queues the input packet.
    ZX_ASSERT(input_free_packet_bits_[free_packet_index]);
  }  // ~lock
  std::unique_ptr<fuchsia::media::Packet> packet = std::make_unique<fuchsia::media::Packet>();
  packet->mutable_header()->set_buffer_lifetime_ordinal(kInputBufferLifetimeOrdinal);
  packet->mutable_header()->set_packet_index(free_packet_index);
  return packet;
}

const CodecBuffer& CodecClient::BlockingGetFreeInputBufferForPacket(
    fuchsia::media::Packet* packet) {
  uint32_t free_buffer_index;
  {  // scope lock
    std::unique_lock<std::mutex> lock(lock_);
    while (input_free_buffer_list_.empty()) {
      input_free_buffer_list_not_empty_.wait(lock);
    }
    free_buffer_index = input_free_buffer_list_.back();
    input_free_buffer_list_.pop_back();
  }  // ~lock
  input_packet_index_to_buffer_index_[packet->header().packet_index()] = free_buffer_index;
  packet->set_buffer_index(free_buffer_index);
  return *all_input_buffers_[free_buffer_index].get();
}

const CodecBuffer& CodecClient::GetInputBufferByIndex(uint32_t packet_index) {
  return *all_input_buffers_[packet_index];
}

const CodecBuffer& CodecClient::GetOutputBufferByIndex(uint32_t packet_index) {
  return *all_output_buffers_[packet_index];
}

void CodecClient::QueueInputFormatDetails(uint64_t stream_lifetime_ordinal,
                                          fuchsia::media::FormatDetails input_format_details) {
  async::PostTask(dispatcher_, [this, stream_lifetime_ordinal,
                                input_format_details = std::move(input_format_details)]() mutable {
    codec_->QueueInputFormatDetails(stream_lifetime_ordinal, std::move(input_format_details));
  });
}

void CodecClient::QueueInputPacket(std::unique_ptr<fuchsia::media::Packet> packet) {
  ZX_ASSERT(packet->has_header());
  ZX_ASSERT(packet->header().has_buffer_lifetime_ordinal());
  ZX_ASSERT(packet->header().has_packet_index());
  ZX_ASSERT(packet->has_buffer_index());
  ZX_ASSERT(packet->has_stream_lifetime_ordinal());
  ZX_ASSERT(packet->has_start_offset());
  ZX_ASSERT(packet->has_valid_length_bytes());
  // timestamp_ish field is optional start_access_unit field is optional
  // known_end_access_unit is optional
  {  // scope lock
    // This packet is already not on the free list, but is still considered free
    // from a protocol point of view, so update that part.
    std::unique_lock<std::mutex> lock(lock_);
    ZX_ASSERT(input_free_packet_bits_[packet->header().packet_index()]);
    input_free_packet_bits_[packet->header().packet_index()] = false;
    // From here it's as if this packet is already in flight with the server.
  }  // ~lock
  async::PostTask(dispatcher_, [this, packet = std::move(packet)]() mutable {
    codec_->QueueInputPacket(std::move(*packet));
    // ~packet
  });
}

void CodecClient::QueueInputEndOfStream(uint64_t stream_lifetime_ordinal) {
  async::PostTask(dispatcher_, [this, stream_lifetime_ordinal] {
    codec_->QueueInputEndOfStream(stream_lifetime_ordinal);
  });
}

void CodecClient::FlushEndOfStreamAndCloseStream(uint64_t stream_lifetime_ordinal) {
  async::PostTask(dispatcher_, [this, stream_lifetime_ordinal] {
    codec_->FlushEndOfStreamAndCloseStream(stream_lifetime_ordinal);
  });
}

std::unique_ptr<CodecOutput> CodecClient::BlockingGetEmittedOutput() {
  while (true) {
    // The rule is that a required pending constraints won't be followed by any
    // more output packets until it's no longer pending (in the sense that the
    // output buffers have been suitably re-configured).  We verify the server
    // is following that rule elsewhere, which means we know here that when both
    // packets are pending and constraints is pending, the packets were
    // delivered to the client first. So we drain the packets first.
    std::unique_ptr<CodecOutput> packet;
    std::shared_ptr<const fuchsia::media::StreamOutputConstraints> constraints;
    {  // scope lock
      std::unique_lock<std::mutex> lock(lock_);
      while (!output_pending_) {
        if (connection_lost_)
          return nullptr;
        output_pending_condition_.wait(lock);
      }
      if (!emitted_output_.empty()) {
        packet = std::move(emitted_output_.front());
        emitted_output_.pop_front();
        // This only does anything when the last packet is consumed and there is
        // no config pending.
        if (!ComputeOutputPendingLocked()) {
          output_pending_ = false;
        }
      } else {
        ZX_ASSERT(output_constraints_action_pending_);
        ZX_ASSERT(last_required_output_constraints_);
        constraints = last_required_output_constraints_;
      }
    }  // ~lock

    // Now we own a packet or have a required config to deal with, but not both,
    // so it doesn't matter which order we check here, but for clarity we check
    // in the same order as above.
    if (packet) {
      return packet;
    }

    // We have a required output config change to deal with here.

    // The server implicitly has relinquished ownership of all output packets
    // and all output buffers as a semantic of the required config change.  This
    // shouldn't really be thought of the packets being "emitted" - rather from
    // the server's point of view they're deallocated already.  Now it's the
    // client's turn to deallocate the old buffers.  It is not permitted to
    // re-use a previous buffer as a new buffer, per protocol rules, not even
    // for the same Codec instance, and not even for a mid-stream output config
    // change.
    //
    // The main mechanism used to detect that the server isn't sending output
    // too soon is output_config_action_pending_.  In contrast, the client code
    // in this example permits itself to send RecycleOutputPacket() after the
    // client has already seen OnOutputConstraints() with action required true,
    // even though the client could stop itself from doing so as a potential
    // optimization.  The client is allowed to send RecycleOutputPacket() up
    // until the implied ReleaseOutputBuffers() at the start of
    // SetOutputSettings().  Between then and a given packet_index becoming
    // emitted again (!free), a RecycleOutputPacket() for that packet_index is
    // forbidden.
    //
    // Because of the client allowing itself to send RecycleOutputPacket() for a
    // while longer than fundamentally necessary, we delay upkeep on
    // output_free_packet_bits_ until here.  This upkeep isn't really fundamentally
    // necessary between OnOutputConstraints() with action required true and the
    // last AddOutputBuffer() as part of output re-configuration, but ... this
    // explicit delayed upkeep _may_ help illustrate how it's acceptable for a
    // client to let the completion end of output processing send
    // RecycleOutputPacket() as long as all those will be sent before
    // SetOutputSettings().
    std::shared_ptr<const fuchsia::media::StreamOutputConstraints> snapped_constraints;
    uint64_t new_output_buffer_lifetime_ordinal;
    {  // scope lock
      std::unique_lock<std::mutex> lock(lock_);

      // We know this because the previous OnOutputConstraints() set this and
      // because we're only here if it's set.
      ZX_ASSERT(output_constraints_action_pending_);
      // We know this because we reject additional output from the server when
      // output_config_action_pending_ is true, and because we've drained all
      // previous output by this point.
      ZX_ASSERT(emitted_output_.empty());
      // We know this because we're only here if we have pending constraints.
      ZX_ASSERT(constraints);

      // Not really critical to do this, as we'll just end up setting these
      // back to true under the same lock hold interval as we set
      // output_config_action_pending_ to false, but see comment above re.
      // how this might help illustrate how late RecycleOutputPacket() can be
      // sent.
      //
      // Think of this assignment as slightly more than a comment in this
      // example, rather than any real need.
      output_free_packet_bits_.resize(0);

      // Free the old output buffers, if any.
      all_output_buffers_.clear();

      // Here is where we snap which exact constraints version we'll actually
      // use.
      //
      // For a client that's doing output buffer re-config on the FIDL thread
      // during OnOutputConstraints with action required true, this will always
      // just be the constraints being presently received.  But this example
      // shows how to drive the codec in a protocol-valid way without being
      // forced to perform buffer re-configuration on the FIDL thread.
      ZX_ASSERT(output_constraints_action_pending_);
      ZX_ASSERT(last_required_output_constraints_);
      ZX_ASSERT(last_output_constraints_);
      // We'll snap the last_output_constraints_, which is always at least as
      // recent as the last_required_output_constraints_.
      snapped_constraints = last_output_constraints_;
      ZX_ASSERT(snapped_constraints);
      new_output_buffer_lifetime_ordinal = next_output_buffer_lifetime_ordinal_;
      next_output_buffer_lifetime_ordinal_ += 2;
    }  // ~lock

    //
    // Tell the server about output settings.
    //

    ZX_ASSERT(snapped_constraints->has_buffer_constraints());
    const fuchsia::media::StreamBufferConstraints& buffer_constraints =
        snapped_constraints->buffer_constraints();

    uint32_t packet_count;
    fuchsia::sysmem::BufferCollectionInfo_2 buffer_collection_info;
    if (!ConfigurePortBufferCollection(true, new_output_buffer_lifetime_ordinal,
                                       buffer_constraints.buffer_constraints_version_ordinal(),
                                       &packet_count, &output_buffer_collection_,
                                       &buffer_collection_info)) {
      FX_LOGS(FATAL) << "ConfigurePortBufferCollection failed (output)";
    }

    // Configure tracking for output buffers.
    {  // scope lock
      std::lock_guard<std::mutex> lock(lock_);

      all_output_buffers_.reserve(packet_count);
      for (uint32_t i = 0; i < packet_count; i++) {
        std::unique_ptr<CodecBuffer> buffer = CodecBuffer::CreateFromVmo(
            i, std::move(buffer_collection_info.buffers[i].vmo),
            static_cast<uint32_t>(buffer_collection_info.buffers[i].vmo_usable_start),
            buffer_collection_info.settings.buffer_settings.size_bytes, true,
            buffer_collection_info.settings.buffer_settings.is_physically_contiguous);
        if (!buffer) {
          FX_LOGS(FATAL) << "CodecBuffer::Allocate() failed (output)";
        }
        ZX_ASSERT(all_output_buffers_.size() == i);
        all_output_buffers_.push_back(std::move(buffer));

        if (i == packet_count - 1) {
          output_free_packet_bits_.resize(packet_count, true);
        }
      }

      current_output_buffer_lifetime_ordinal_ = new_output_buffer_lifetime_ordinal;
    }  // ~lock

    // We're ready to receive output.
    PostToFidlThread([this, output_buffer_lifetime_ordinal = new_output_buffer_lifetime_ordinal] {
      if (!codec_) {
        return;
      }
      if (output_buffer_lifetime_ordinal != current_output_buffer_lifetime_ordinal_) {
        return;
      }
      codec_->CompleteOutputBufferPartialSettings(output_buffer_lifetime_ordinal);
    });

    {  // scope lock
      std::lock_guard<std::mutex> lock(lock_);

      // So, now that we're done with that output re-config, it's time to see if
      // that re-config was the last one we need to do, or if there's a newer
      // config that's action-required.

      if (snapped_constraints->buffer_constraints().buffer_constraints_version_ordinal() >=
          last_required_output_constraints_->buffer_constraints()
              .buffer_constraints_version_ordinal()) {
        // Good.  The client is caught up.  The output_config_action_pending_
        // can become false here, but may very shortly become true again if
        // another OnOutputConstraints() is received after we release the lock
        // (roughly speaking; see code).
        //
        // It's ok that we didn't set output_config_action_pending_ to false
        // before sending the last AddOutputBuffer() above, because
        // OnOutputConstraints() was still able to update
        // last_required_output_config_ as needed, which it's been able to do
        // all along during most of this whole method.  If we had set to false
        // up there, it would probably be less obvious why it works vs. here,
        // but either can work.
        FX_VLOGS(3) << "output_config_action_pending_ = false, because client "
                       "caught up";
        output_constraints_action_pending_ = false;
        // Because this was true for at least pending config reason which we
        // are only just clearing immediately above.
        ZX_ASSERT(output_pending_);
        // There can be output packets by this point so only clear
        // output_pending_ if there are also no packets.
        if (!ComputeOutputPendingLocked()) {
          output_pending_ = false;
        }
      } else {
        // We've received and even more recent constraints that's
        // action-required, so go around again without clearing
        // output_constraints_action_pending_ or output_pending_. Both remain
        // true until we've caught up to a config that's at least as new as the
        // last_required_output_constraints_.
        FX_VLOGS(3) << "output_constraints_action_pending_ remains true because server "
                       "has sent yet another action-required output constraints";
        ZX_ASSERT(output_constraints_action_pending_);
        ZX_ASSERT(output_pending_);
      }
    }  // ~lock
  }
}

bool CodecClient::ConfigurePortBufferCollection(
    bool is_output, uint64_t new_buffer_lifetime_ordinal,
    uint64_t buffer_constraints_version_ordinal, uint32_t* out_packet_count,
    fuchsia::sysmem::BufferCollectionPtr* out_buffer_collection,
    fuchsia::sysmem::BufferCollectionInfo_2* out_buffer_collection_info) {
  fuchsia::media::StreamBufferPartialSettings settings;
  settings.set_buffer_lifetime_ordinal(new_buffer_lifetime_ordinal);
  settings.set_buffer_constraints_version_ordinal(buffer_constraints_version_ordinal);

  fuchsia::sysmem::BufferCollectionSyncPtr buffer_collection;
  fidl::InterfaceHandle<fuchsia::sysmem::BufferCollectionToken> codec_sysmem_token;
  if (!CreateAndSyncBufferCollection(&buffer_collection, &codec_sysmem_token)) {
    FX_LOGS(FATAL) << "CreateAndSyncBufferCollection failed (output)";
    return false;
  }

  settings.set_sysmem_token(std::move(codec_sysmem_token));

  fuchsia::sysmem::BufferCollectionConstraints constraints;
  // TODO(fxbug.dev/24581): Hardcoded to read/write to allow direct Vulkan import on
  // UMA platforms.
  if (!is_output && is_input_secure_) {
    constraints.usage.video = fuchsia::sysmem::videoUsageDecryptorOutput;
  } else if (is_output && is_output_secure_) {
    // Only used if kVerifySecureOutput is used in test.
    constraints.usage.cpu =
        fuchsia::sysmem::cpuUsageReadOften | fuchsia::sysmem::cpuUsageWriteOften;
  } else {
    constraints.usage.cpu =
        fuchsia::sysmem::cpuUsageReadOften | fuchsia::sysmem::cpuUsageWriteOften;
  }

  // TODO(dustingreen): Make this more flexible once we're more flexible on
  // frame_count on output of decoder.
  if (is_output) {
    constraints.min_buffer_count_for_camping = kMinInputBufferCountForCamping;
  } else {
    constraints.min_buffer_count_for_camping = kMinOutputBufferCountForCamping;
  }
  ZX_DEBUG_ASSERT(constraints.min_buffer_count_for_dedicated_slack == 0);
  ZX_DEBUG_ASSERT(constraints.min_buffer_count_for_shared_slack == 0);

  // 0 is treated as 0xFFFFFFFF.
  ZX_DEBUG_ASSERT(constraints.max_buffer_count == 0);

  constraints.has_buffer_memory_constraints = true;
  // Sysmem has a built-in min_size_bytes of 1, so no need to really constrain
  // min_size_bytes here, unless output, in which case setting a min_size_bytes
  // allows for seamless video frame dimension changes.  If the client code says
  // 0 that's fine.
  //
  // Similar for min_buffer_count, but min of 0 means 0 / no constraint in that case.
  ZX_DEBUG_ASSERT(constraints.buffer_memory_constraints.min_size_bytes == 0);
  ZX_DEBUG_ASSERT(constraints.min_buffer_count == 0);
  if (is_output) {
    constraints.buffer_memory_constraints.min_size_bytes = min_output_buffer_size_;
    constraints.min_buffer_count = min_output_buffer_count_;
  } else {
    constraints.buffer_memory_constraints.min_size_bytes = min_input_buffer_size_;
  }
  constraints.buffer_memory_constraints.max_size_bytes = std::numeric_limits<uint32_t>::max();
  constraints.buffer_memory_constraints.physically_contiguous_required = false;
  constraints.buffer_memory_constraints.secure_required = false;
  if (is_output && is_output_secure_) {
    constraints.buffer_memory_constraints.inaccessible_domain_supported = true;
  } else if (!is_output && is_input_secure_) {
    constraints.buffer_memory_constraints.cpu_domain_supported = false;
    constraints.buffer_memory_constraints.ram_domain_supported = false;
    constraints.buffer_memory_constraints.inaccessible_domain_supported = true;
    constraints.buffer_memory_constraints.secure_required = true;
    constraints.buffer_memory_constraints.heap_permitted_count = 1;
    constraints.buffer_memory_constraints.heap_permitted[0] =
        fuchsia::sysmem::HeapType::AMLOGIC_SECURE_VDEC;
  } else {
    ZX_DEBUG_ASSERT(!constraints.buffer_memory_constraints.inaccessible_domain_supported);
    ZX_DEBUG_ASSERT(constraints.buffer_memory_constraints.cpu_domain_supported);
  }

  ZX_DEBUG_ASSERT(!constraints.buffer_memory_constraints.ram_domain_supported);

  if (is_output_tiled_) {
    constraints.image_format_constraints_count = 1;
    auto& image_format = constraints.image_format_constraints[0];
    image_format.color_spaces_count = 1;
    image_format.color_space[0].type = fuchsia::sysmem::ColorSpaceType::REC709;
    image_format.pixel_format.type = fuchsia::sysmem::PixelFormatType::NV12;
    image_format.pixel_format.has_format_modifier = true;
    image_format.pixel_format.format_modifier.value =
        fuchsia::sysmem::FORMAT_MODIFIER_INTEL_I915_Y_TILED;
  } else {
    // Despite being a consumer of output uncompressed video frames (when decoding
    // video and is_output), for now we intentionally don't constrain to the
    // PixelFormatType(s) that we can consume, and instead fail later if we get
    // something unexpected on output. That's just easier than plumbing
    // PixelFormatType(s) to here for now.
    ZX_DEBUG_ASSERT(constraints.image_format_constraints_count == 0);
  }

  PostToFidlThread([this, is_output, settings = std::move(settings)]() mutable {
    if (!codec_) {
      return;
    }
    if (is_output) {
      codec_->SetOutputBufferPartialSettings(std::move(settings));
    } else {
      codec_->SetInputBufferPartialSettings(std::move(settings));
    }
  });

  buffer_collection->SetConstraints(true, std::move(constraints));

  fuchsia::sysmem::BufferCollectionInfo_2 buffer_collection_info;
  // This borrows buffer_collection during
  // the call.
  if (!WaitForSysmemBuffersAllocated(is_output, &buffer_collection, &buffer_collection_info)) {
    FX_LOGS(FATAL) << "WaitForSysmemBuffer"
                      "sAllocated failed";
    return false;
  }

  if (!in_lax_mode_) {
    // We don't expect normal cases to go above kMaxExpectedBufferCount, but if
    // min_output_buffer_count_ forces higher buffer counts, that's fine.
    ZX_ASSERT(buffer_collection_info.buffer_count <= kMaxExpectedBufferCount ||
              min_output_buffer_count_ > kMaxExpectedBufferCount);
  }

  fuchsia::sysmem::BufferCollectionPtr buffer_collection_ptr;

  // For the Bind() we probably don't strictly need to be on FIDL thread, so do
  // the Bind() here.  This does mean we need to set the error handler before
  // the Bind() however.
  buffer_collection_ptr.set_error_handler([is_output](zx_status_t status) {
    FX_PLOGS(FATAL, status) << "BufferCollection failed is_output: " << is_output;
  });

  // This implicitly converts buffer_collection from
  // fidl::SynchronousInterfacePtr<> to fidl::InterfaceHandle<>, which is what
  // we want; we're moving handling of the BufferCollection from this thread to
  // the FIDL thread.
  zx_status_t bind_status = buffer_collection_ptr.Bind(std::move(buffer_collection), dispatcher_);
  if (bind_status != ZX_OK) {
    FX_PLOGS(FATAL, bind_status) << "buffer_collection_ptr.Bind() failed is_output: " << is_output;
    return false;
  }

  *out_packet_count = buffer_collection_info.buffer_count;
  *out_buffer_collection = std::move(buffer_collection_ptr);
  *out_buffer_collection_info = std::move(buffer_collection_info);
  return true;
}

void CodecClient::RecycleOutputPacket(fuchsia::media::PacketHeader free_packet) {
  ZX_ASSERT(free_packet.has_packet_index());
  {  // scope lock
    std::unique_lock<std::mutex> lock(lock_);
    output_free_packet_bits_[free_packet.packet_index()] = true;
  }  // ~lock
  async::PostTask(dispatcher_, [this, free_packet = std::move(free_packet)]() mutable {
    codec_->RecycleOutputPacket(std::move(free_packet));
  });
}

void CodecClient::OnOutputConstraints(fuchsia::media::StreamOutputConstraints output_constraints) {
  bool output_pending_notify_needed = false;
  // Not that the std::move() actaully helps here, but that's what we're doing.
  std::shared_ptr<fuchsia::media::StreamOutputConstraints> shared_constraints =
      std::make_shared<fuchsia::media::StreamOutputConstraints>(std::move(output_constraints));
  {  // scope lock
    std::unique_lock<std::mutex> lock(lock_);

    if (!shared_constraints->has_stream_lifetime_ordinal()) {
      FX_LOGS(FATAL) << "StreamOutputConstraints missing stream_lifetime_ordinal";
    }
    uint64_t stream_lifetime_ordinal = shared_constraints->stream_lifetime_ordinal();
    TrackOutputStreamLifetimeOrdinal(stream_lifetime_ordinal);

    ZX_ASSERT(
        !last_output_constraints_ ||
        (last_output_constraints_->has_buffer_constraints() &&
         last_output_constraints_->buffer_constraints().has_buffer_constraints_version_ordinal()));
    uint64_t previous_buffer_constraints_version_ordinal =
        last_output_constraints_
            ? last_output_constraints_->buffer_constraints().buffer_constraints_version_ordinal()
            : 0;
    ZX_ASSERT(shared_constraints->has_buffer_constraints() &&
              shared_constraints->buffer_constraints().has_buffer_constraints_version_ordinal());
    if (shared_constraints->buffer_constraints().buffer_constraints_version_ordinal() <
        previous_buffer_constraints_version_ordinal) {
      FX_LOGS(FATAL) << "broken server sent badly ordered buffer constraints ordinals";
    }
    if ((shared_constraints->has_buffer_constraints_action_required() &&
         shared_constraints->buffer_constraints_action_required()) &&
        shared_constraints->buffer_constraints().buffer_constraints_version_ordinal() <=
            previous_buffer_constraints_version_ordinal) {
      FX_LOGS(FATAL) << "broken server sent buffer_constraints_action_required without "
                        "increasingbuffer_constraints_version_ordinal";
    }
    last_output_constraints_ = shared_constraints;
    FX_VLOGS(3) << "OnOutputConstraints buffer_constraints_version_ordinal: "
                << shared_constraints->buffer_constraints().buffer_constraints_version_ordinal()
                << "buffer_constraints_action_required: "
                << shared_constraints->buffer_constraints_action_required();
    if (shared_constraints->buffer_constraints_action_required()) {
      last_required_output_constraints_ = shared_constraints;
      // A client is allowed to forget the output format on any action required
      // buffer constraints, so forget here.
      last_output_format_ = nullptr;
      FX_VLOGS(3) << "output_config_action_pending_ = true, because received a "
                     "buffer_constraints_action_required constraints\n";
      output_constraints_action_pending_ = true;
      if (!output_pending_) {
        output_pending_ = true;
        output_pending_notify_needed = true;
      }
    }
  }  // ~lock
  if (output_pending_notify_needed) {
    output_pending_condition_.notify_all();
  }
}

void CodecClient::OnOutputFormat(fuchsia::media::StreamOutputFormat output_format) {
  // We don't need to notify output_pending_condition_ since in contrast to
  // constraints we don't need to take action, and nobody cares about the format
  // until the next packet arrives.
  std::shared_ptr<fuchsia::media::StreamOutputFormat> shared_format =
      std::make_shared<fuchsia::media::StreamOutputFormat>(std::move(output_format));
  std::unique_lock<std::mutex> lock(lock_);

  if (!shared_format->has_stream_lifetime_ordinal()) {
    FX_LOGS(FATAL) << "StreamOutputFormat missing stream_lifetime_ordinal";
  }
  uint64_t stream_lifetime_ordinal = shared_format->stream_lifetime_ordinal();
  TrackOutputStreamLifetimeOrdinal(stream_lifetime_ordinal);

  if (is_format_since_last_packet_) {
    // A server can easily elide unnecessary OnOutputFormat by not sending
    // OnOutputFormat until immediately before OnOutputPacket.  The format is
    // logically part of each output packet, with the optimization that we only
    // send output format when it changes, in between packets, to avoid needing
    // to send output format with every packet.
    FX_LOGS(FATAL) << "broken server sent two OnOutputFormat() in a row";
  }
  if (!shared_format->has_stream_lifetime_ordinal()) {
    FX_LOGS(FATAL) << "OnOutputFormat !has_stream_lifetime_ordinal()";
  }
  if (!shared_format->has_format_details()) {
    FX_LOGS(FATAL) << "OnOutputFormat !has_format_details()";
  }
  last_output_format_ = shared_format;
  is_format_since_last_packet_ = true;
}

void CodecClient::OnOutputPacket(fuchsia::media::Packet output_packet, bool error_detected_before,
                                 bool error_detected_during) {
  FX_CHECK(output_packet.has_header());
  FX_CHECK(output_packet.has_stream_lifetime_ordinal());
  FX_CHECK(output_packet.header().has_packet_index());
  bool output_pending_notify_needed = false;
  std::unique_ptr<const fuchsia::media::Packet> local_packet =
      std::make_unique<fuchsia::media::Packet>(std::move(output_packet));
  uint32_t packet_index = local_packet->header().packet_index();

  {  // scope lock
    std::unique_lock<std::mutex> lock(lock_);

    if (!local_packet->has_stream_lifetime_ordinal()) {
      FX_LOGS(FATAL) << "Packet missing stream_lifetime_ordinal";
    }
    uint64_t stream_lifetime_ordinal = local_packet->stream_lifetime_ordinal();
    TrackOutputStreamLifetimeOrdinal(stream_lifetime_ordinal);
    if (!last_output_format_ ||
        last_output_format_->stream_lifetime_ordinal() != stream_lifetime_ordinal) {
      FX_LOGS(FATAL) << "OnOutputFormat required before OnOutputPacket, per-stream";
    }

    std::unique_ptr<CodecOutput> output =
        std::make_unique<CodecOutput>(stream_lifetime_ordinal, last_output_constraints_,
                                      last_output_format_, std::move(local_packet), false, false);
    if (output_constraints_action_pending_) {
      // FWIW, we wouldn't be able to detect this if we were using the
      // async::Loop thread to perform output buffer re-configuration.
      FX_LOGS(FATAL) << "server incorrectly sent output packet while required "
                        "constraints change pending";
    }
    if (!output_free_packet_bits_[packet_index]) {
      // The packet was emitted twice by the server without it becoming free in
      // between, which is broken server behavior.
      FX_LOGS(FATAL) << "server incorrectly emitted an output packet without it becoming "
                        "free in between";
    }
    // Emitted by server, so not free until later when we send it back to server
    // with RecycleOutputPacket(), or until we re-configure output buffers in
    // which case all the output packets start free with the server.
    output_free_packet_bits_[packet_index] = false;
    emitted_output_.push_back(std::move(output));
    is_format_since_last_packet_ = false;
    if (!output_pending_) {
      output_pending_ = true;
      output_pending_notify_needed = true;
    }
  }  // ~lock
  if (output_pending_notify_needed) {
    output_pending_condition_.notify_all();
  }
}

void CodecClient::OnOutputEndOfStream(uint64_t stream_lifetime_ordinal,
                                      bool error_detected_before) {
  bool output_pending_notify_needed = false;
  std::unique_ptr<CodecOutput> output = std::make_unique<CodecOutput>(
      stream_lifetime_ordinal, nullptr, nullptr, nullptr, true, false);
  {  // scope lock
    std::unique_lock<std::mutex> lock(lock_);
    if (output_constraints_action_pending_) {
      // FWIW, we wouldn't be able to detect this if we were using the
      // async::Loop thread to perform output buffer re-configuration.
      FX_LOGS(FATAL) << "server incorrectly sent OnOutputEndOfStream() while "
                        "required constraints change pending";
    }
    emitted_output_.push_back(std::move(output));
    if (!output_pending_) {
      output_pending_ = true;
      output_pending_notify_needed = true;
    }
  }  // ~lock
  if (output_pending_notify_needed) {
    output_pending_condition_.notify_all();
  }
}

void CodecClient::OnStreamFailed(uint64_t stream_lifetime_ordinal,
                                 fuchsia::media::StreamError error) {
  FX_LOGS(INFO) << "OnStreamFailed()";
  bool output_pending_notify_needed = false;
  std::unique_ptr<CodecOutput> output = std::make_unique<CodecOutput>(
      stream_lifetime_ordinal, nullptr, nullptr, nullptr, false, true);
  {  // scope lock
    std::unique_lock<std::mutex> lock(lock_);
    emitted_output_.push_back(std::move(output));
    if (!output_pending_) {
      output_pending_ = true;
      output_pending_notify_needed = true;
    }
  }  // ~lock
  if (output_pending_notify_needed) {
    output_pending_condition_.notify_all();
  }
  //  FX_LOGS(FATAL) << "OnStreamFailed: stream_lifetime_ordinal: " << stream_lifetime_ordinal
  //                 << " error: " << std::hex << static_cast<uint32_t>(error);
}
