// 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 "use_video_decoder.h"

#include "codec_client.h"
#include "util.h"

#include <garnet/lib/media/raw_video_writer/raw_video_writer.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/fidl/cpp/clone.h>
#include <lib/fit/defer.h>
#include <lib/fxl/arraysize.h>
#include <lib/fxl/logging.h>
#include <lib/media/codec_impl/fourcc.h>
#include <lib/media/test/frame_sink.h>

#include <stdint.h>
#include <string.h>
#include <thread>

namespace {

constexpr bool kRawVideoWriterEnabled = true;

// This example only has one stream_lifetime_ordinal which is 1.
//
// TODO(dustingreen): actually re-use the Codec instance for at least one more
// stream, even if it's just to decode the same data again.
constexpr uint64_t kStreamLifetimeOrdinal = 1;

// Scenic ImagePipe doesn't allow image_id 0, so offset by this much.
constexpr uint32_t kFirstValidImageId = 1;

constexpr uint8_t kLongStartCodeArray[] = {0x00, 0x00, 0x00, 0x01};
constexpr uint8_t kShortStartCodeArray[] = {0x00, 0x00, 0x01};

// If readable_bytes is 0, that's considered a "start code", to allow the caller
// to terminate a NAL the same way regardless of whether another start code is
// found or the end of the buffer is found.
//
// ptr has readable_bytes of data - the function only evaluates whether there is
// a start code at the begining of the data at ptr.
//
// readable_bytes - the caller indicates how many bytes are readable starting at
// ptr.
//
// *start_code_size_bytes will have length of the start code in bytes when the
// function returns true - unchanged otherwise.  Normally this would be 3 or 4,
// but a 0 is possible if readable_bytes is 0.
bool is_start_code(uint8_t* ptr, size_t readable_bytes,
                   size_t* start_code_size_bytes_out) {
  if (readable_bytes == 0) {
    *start_code_size_bytes_out = 0;
    return true;
  }
  if (readable_bytes >= 4) {
    if (!memcmp(ptr, kLongStartCodeArray, sizeof(kLongStartCodeArray))) {
      *start_code_size_bytes_out = 4;
      return true;
    }
  }
  if (readable_bytes >= 3) {
    if (!memcmp(ptr, kShortStartCodeArray, sizeof(kShortStartCodeArray))) {
      *start_code_size_bytes_out = 3;
      return true;
    }
  }
  return false;
}

// Test-only.  Not for production use.  Caller must ensure there are at least 5
// bytes at nal_unit.
uint8_t GetNalUnitType(const uint8_t* nal_unit) {
  // Also works with 4-byte startcodes.
  static const uint8_t start_code[3] = {0, 0, 1};
  uint8_t* next_start = static_cast<uint8_t*>(memmem(nal_unit, 5, start_code,
                                                     sizeof(start_code))) +
                        sizeof(start_code);
  return *next_start & 0xf;
}

struct __attribute__((__packed__)) IvfHeader {
  uint32_t signature;
  uint16_t version;
  uint16_t header_length;
  uint32_t fourcc;
  uint16_t width;
  uint16_t height;
  uint32_t frame_rate;
  uint32_t time_scale;
  uint32_t frame_count;
  uint32_t unused;
};

struct __attribute__((__packed__)) IvfFrameHeader {
  uint32_t size_bytes;
  uint64_t presentation_timestamp;
};

enum class Format {
  kH264,
  kVp9,
};

}  // namespace

void QueueH264Frames(CodecClient* codec_client, uint8_t* input_bytes,
                     size_t input_size) {
  // We assign fake PTS values starting at 0 partly to verify that 0 is
  // treated as a valid PTS.
  uint64_t input_frame_pts_counter = 0;
  // Raw .h264 has start code 00 00 01 or 00 00 00 01 before each NAL, and
  // the start codes don't alias in the middle of NALs, so we just scan
  // for NALs and send them in to the decoder.
  auto queue_access_unit = [&codec_client, &input_bytes,
                            &input_frame_pts_counter](uint8_t* bytes,
                                                      size_t byte_count) {
    size_t bytes_so_far = 0;
    // printf("queuing offset: %ld byte_count: %zu\n", bytes -
    // input_bytes.get(), byte_count);
    while (bytes_so_far != byte_count) {
      std::unique_ptr<fuchsia::mediacodec::CodecPacket> packet =
          codec_client->BlockingGetFreeInputPacket();
      // For input we do buffer_index == packet_index.
      const CodecBuffer& buffer =
          codec_client->GetInputBufferByIndex(packet->header.packet_index);
      size_t bytes_to_copy =
          std::min(byte_count - bytes_so_far, buffer.size_bytes());
      packet->stream_lifetime_ordinal = kStreamLifetimeOrdinal;
      packet->start_offset = 0;
      packet->valid_length_bytes = bytes_to_copy;

      packet->has_timestamp_ish = false;
      packet->timestamp_ish = 0;
      if (bytes_so_far == 0) {
        uint8_t nal_unit_type = GetNalUnitType(bytes);
        if (nal_unit_type == 1 || nal_unit_type == 5) {
          packet->has_timestamp_ish = true;
          packet->timestamp_ish = input_frame_pts_counter++;
        }
      }

      packet->start_access_unit = (bytes_so_far == 0);
      packet->known_end_access_unit =
          (bytes_so_far + bytes_to_copy == byte_count);
      memcpy(buffer.base(), bytes + bytes_so_far, bytes_to_copy);
      codec_client->QueueInputPacket(std::move(packet));
      bytes_so_far += bytes_to_copy;
    }
  };
  for (size_t i = 0; i < input_size;) {
    // Until clang-tidy correctly interprets Exit(), this "= 0" satisfies it.
    size_t start_code_size_bytes = 0;
    if (!is_start_code(&input_bytes[i], input_size - i,
                       &start_code_size_bytes)) {
      if (i == 0) {
        Exit(
            "Didn't find a start code at the start of the file, and this "
            "example doesn't scan forward (for now).");
      } else {
        Exit(
            "Fell out of sync somehow - previous NAL offset + previous "
            "NAL length not a start code.");
      }
    }
    if (i + start_code_size_bytes == input_size) {
      Exit("Start code at end of file unexpected");
    }
    size_t nal_start_offset = i + start_code_size_bytes;
    // Scan for end of NAL.  The end of NAL can be because we're out of
    // data, or because we hit another start code.
    size_t find_end_iter = nal_start_offset;
    size_t ignore_start_code_size_bytes;
    while (find_end_iter <= input_size &&
           !is_start_code(&input_bytes[find_end_iter],
                          input_size - find_end_iter,
                          &ignore_start_code_size_bytes)) {
      find_end_iter++;
    }
    FXL_DCHECK(find_end_iter <= input_size);
    if (find_end_iter == nal_start_offset) {
      Exit("Two adjacent start codes unexpected.");
    }
    FXL_DCHECK(find_end_iter > nal_start_offset);
    size_t nal_length = find_end_iter - nal_start_offset;
    queue_access_unit(&input_bytes[i], start_code_size_bytes + nal_length);
    // start code + NAL payload
    i += start_code_size_bytes + nal_length;
  }

  // Send through QueueInputEndOfStream().
  codec_client->QueueInputEndOfStream(kStreamLifetimeOrdinal);
  // We flush and close to run the handling code server-side.  However, we don't
  // yet verify that this successfully achieves what it says.
  codec_client->FlushEndOfStreamAndCloseStream(kStreamLifetimeOrdinal);
  // input thread done
}
void QueueVp9Frames(CodecClient* codec_client, uint8_t* input_bytes,
                    size_t input_size) {
  auto queue_access_unit = [&codec_client, &input_bytes](uint8_t* bytes,
                                                         size_t byte_count,
                                                         uint32_t frame_pts) {
    std::unique_ptr<fuchsia::mediacodec::CodecPacket> packet =
        codec_client->BlockingGetFreeInputPacket();
    // For input we do buffer_index == packet_index.
    const CodecBuffer& buffer =
        codec_client->GetInputBufferByIndex(packet->header.packet_index);
    // VP9 decoder doesn't yet support splitting access units into multiple
    // packets.
    FXL_DCHECK(byte_count <= buffer.size_bytes());
    packet->stream_lifetime_ordinal = kStreamLifetimeOrdinal;
    packet->start_offset = 0;
    packet->valid_length_bytes = byte_count;

    packet->has_timestamp_ish = true;
    packet->timestamp_ish = frame_pts;

    packet->start_access_unit = true;
    packet->known_end_access_unit = true;
    memcpy(buffer.base(), bytes, byte_count);
    codec_client->QueueInputPacket(std::move(packet));
  };
  IvfHeader* header = (IvfHeader*)&input_bytes[0];
  for (size_t i = header->header_length; i < input_size;) {
    if (i + sizeof(IvfFrameHeader) > input_size)
      Exit("Frame header truncated.");
    IvfFrameHeader* frame_header = (IvfFrameHeader*)&input_bytes[i];
    if (i + sizeof(IvfFrameHeader) + frame_header->size_bytes > input_size)
      Exit("Frame truncated.");
    queue_access_unit(&input_bytes[i + sizeof(IvfFrameHeader)],
                      frame_header->size_bytes,
                      frame_header->presentation_timestamp);
    i += sizeof(IvfFrameHeader) + frame_header->size_bytes;
  }

  // Send through QueueInputEndOfStream().
  codec_client->QueueInputEndOfStream(kStreamLifetimeOrdinal);
  // We flush and close to run the handling code server-side.  However, we don't
  // yet verify that this successfully achieves what it says.
  codec_client->FlushEndOfStreamAndCloseStream(kStreamLifetimeOrdinal);
  // input thread done
}

static void use_video_decoder(
    async::Loop* main_loop, fuchsia::mediacodec::CodecFactoryPtr codec_factory,
    Format format, const std::string& input_file,
    const std::string& output_file, uint8_t md_out[SHA256_DIGEST_LENGTH],
    std::vector<std::pair<bool, uint64_t>>* timestamps_out,
    FrameSink* frame_sink) {
  VLOGF("use_h264_decoder()\n");
  FXL_DCHECK(!timestamps_out || timestamps_out->empty());
  memset(md_out, 0, SHA256_DIGEST_LENGTH);
  async::Loop loop(&kAsyncLoopConfigNoAttachToThread);
  loop.StartThread("use_h264_decoder_loop");

  // payload data for bear.h264 is 00 00 00 01 start code before each NAL, with
  // SPS / PPS NALs and also frame NALs.  We deliver to Codec NAL-by-NAL without
  // the start code, since the Codec packet
  VLOGF("reading h264 file...\n");
  size_t input_size;
  std::unique_ptr<uint8_t[]> input_bytes =
      read_whole_file(input_file.c_str(), &input_size);
  VLOGF("done reading h264 file.\n");

  // Since the .h264 file has SPS + PPS NALs in addition to frame NALs, we don't
  // use codec_oob_bytes for this stream.
  //
  // TODO(dustingreen): Determine for .mp4 or similar which don't have SPS / PPS
  // in band whether .mp4 provides ongoing OOB data, or just at the start, and
  // document in codec.fidl how that's to be handled.

  VLOGF("before CodecClient::CodecClient()...\n");
  CodecClient codec_client(&loop);

  const char* mime_type;
  switch (format) {
    case Format::kH264:
      mime_type = "video/h264";
      break;

    case Format::kVp9:
      mime_type = "video/vp9";
      break;
  }

  async::PostTask(
      main_loop->dispatcher(),
      [&codec_factory, codec_client_request = codec_client.GetTheRequestOnce(),
       mime_type]() mutable {
        VLOGF("before codec_factory->CreateDecoder() (async)\n");
        codec_factory->CreateDecoder(
            fuchsia::mediacodec::CreateDecoder_Params{
                .input_details.format_details_version_ordinal = 0,
                .input_details.mime_type = mime_type,
                // This is required for timestamp_ish values to transit the
                // Codec.
                .promise_separate_access_units_on_input = true,
            },
            std::move(codec_client_request));
      });

  VLOGF("before codec_client.Start()...\n");
  // This does a Sync(), so after this we can drop the CodecFactory without it
  // potentially cancelling our Codec create.
  codec_client.Start();

  // We don't need the CodecFactory any more, and at this point any Codec
  // creation errors have had a chance to arrive via the
  // codec_factory.set_error_handler() lambda.
  //
  // Unbind() is only safe to call on the interfaces's dispatcher thread.  We
  // also want to block the current thread until this is done, to avoid
  // codec_factory potentially disapearing before this posted work finishes.
  std::mutex unbind_mutex;
  std::condition_variable unbind_done_condition;
  bool unbind_done = false;
  async::PostTask(
      main_loop->dispatcher(),
      [&codec_factory, &unbind_mutex, &unbind_done, &unbind_done_condition] {
        codec_factory.Unbind();
        {  // scope lock
          std::lock_guard<std::mutex> lock(unbind_mutex);
          unbind_done = true;
        }  // ~lock
        unbind_done_condition.notify_all();
        // All of codec_factory, unbind_mutex, unbind_done,
        // unbind_done_condition are potentially gone by this point.
      });
  {  // scope lock
    std::unique_lock<std::mutex> lock(unbind_mutex);
    while (!unbind_done) {
      unbind_done_condition.wait(lock);
    }
  }  // ~lock
  FXL_DCHECK(unbind_done);

  VLOGF("before starting in_thread...\n");
  std::unique_ptr<std::thread> in_thread = std::make_unique<std::thread>(
      [&codec_client, &input_bytes, input_size, format]() {
        switch (format) {
          case Format::kH264:
            QueueH264Frames(&codec_client, input_bytes.get(), input_size);
            break;

          case Format::kVp9:
            QueueVp9Frames(&codec_client, input_bytes.get(), input_size);
            break;
        }
      });

  // Separate thread to process the output.
  //
  // codec_client outlives the thread (and for separate reasons below, all the
  // frame_sink activity started by out_thread).
  std::unique_ptr<std::thread> out_thread = std::make_unique<
      std::thread>([main_loop, &codec_client, output_file, md_out,
                    &timestamps_out, frame_sink]() {
    // The codec_client lock_ is not held for long durations in here, which is
    // good since we're using this thread to do things like write to an output
    // file.
    media::RawVideoWriter<kRawVideoWriterEnabled> raw_video_writer(
        output_file.c_str());
    SHA256_CTX sha256_ctx;
    SHA256_Init(&sha256_ctx);
    // We allow the server to send multiple output format updates if it wants;
    // see implementation of BlockingGetEmittedOutput() which will hide
    // multiple configs before the first packet from this code.
    //
    // In this example, we only deal with one output format once we start seeing
    // stream output data show up, since our raw_video_writer is only really
    // meant to store one format per file.
    std::shared_ptr<const fuchsia::mediacodec::CodecOutputConfig> stream_config;
    const fuchsia::mediacodec::VideoUncompressedFormat* raw = nullptr;
    while (true) {
      std::unique_ptr<CodecOutput> output =
          codec_client.BlockingGetEmittedOutput();
      if (output->stream_lifetime_ordinal() != kStreamLifetimeOrdinal) {
        Exit(
            "server emitted a stream_lifetime_ordinal that client didn't set "
            "on any input");
      }
      if (output->end_of_stream()) {
        VLOGF("output end_of_stream() - done with output\n");
        // Just "break;" would be more fragile under code modification.
        goto end_of_output;
      }

      const fuchsia::mediacodec::CodecPacket& packet = output->packet();
      // cleanup can run on any thread, and codec_client.RecycleOutputPacket()
      // is ok with that.  In addition, cleanup can run after codec_client is
      // gone, since we don't block return from use_h264_decoder() on Scenic
      // actually freeing up all previously-queued frames.
      auto cleanup = fit::defer(
          [&codec_client, packet_header = fidl::Clone(packet.header)] {
            // Using an auto call for this helps avoid losing track of the
            // output_buffer.
            //
            // If the omx_state_ or omx_state_desired_ isn't correct,
            // UseOutputBuffer() will fail.  The only way that can happen here
            // is if the OMX codec transitioned states unilaterally without any
            // set state command, so if that occurs, exit.
            codec_client.RecycleOutputPacket(std::move(packet_header));
          });
      std::shared_ptr<const fuchsia::mediacodec::CodecOutputConfig> config =
          output->config();
      // This will remain live long enough because this thread is the only
      // thread that re-allocates output buffers.
      const CodecBuffer& buffer =
          codec_client.GetOutputBufferByIndex(packet.buffer_index);

      if (stream_config &&
          (config->format_details.format_details_version_ordinal !=
           stream_config->format_details.format_details_version_ordinal)) {
        Exit(
            "codec server unexpectedly changed output format mid-stream - "
            "unexpected for this stream");
      }

      if (packet.valid_length_bytes == 0) {
        // The server should not generate any empty packets.
        Exit("broken server sent empty packet");
      }

      // We have a non-empty packet of the stream.

      if (!stream_config) {
        // Every output has a config.  This happens exactly once.
        stream_config = config;
        const fuchsia::mediacodec::CodecFormatDetails& format =
            stream_config->format_details;
        if (!format.domain->is_video()) {
          Exit("!format.domain.is_video()");
        }
        const fuchsia::mediacodec::VideoFormat& video_format =
            format.domain->video();
        if (!video_format.is_uncompressed()) {
          Exit("!video.is_uncompressed()");
        }

        raw = &video_format.uncompressed();
        switch (raw->fourcc) {
          case make_fourcc('N', 'V', '1', '2'): {
            size_t y_size =
                raw->primary_height_pixels * raw->primary_line_stride_bytes;
            if (raw->secondary_start_offset < y_size) {
              Exit("raw.secondary_start_offset < y_size");
            }
            // NV12 requires UV be same line stride as Y.
            size_t total_size =
                raw->secondary_start_offset +
                raw->primary_height_pixels / 2 * raw->primary_line_stride_bytes;
            if (packet.valid_length_bytes < total_size) {
              Exit("packet.valid_length_bytes < total_size");
            }
            break;
          }
          case make_fourcc('Y', 'V', '1', '2'): {
            size_t y_size =
                raw->primary_height_pixels * raw->primary_line_stride_bytes;
            size_t v_size =
                raw->secondary_height_pixels * raw->secondary_line_stride_bytes;
            size_t u_size = v_size;
            size_t total_size = y_size + u_size + v_size;

            if (packet.valid_length_bytes < total_size) {
              Exit("packet.valid_length_bytes < total_size");
            }

            if (raw->secondary_start_offset < y_size) {
              Exit("raw.secondary_start_offset < y_size");
            }

            if (raw->tertiary_start_offset < y_size + v_size) {
              Exit("raw.tertiary_start_offset < y_size + v_size");
            }
            break;
          }
          default:
            Exit("fourcc != NV12 && fourcc != YV12");
        }
      }
      if (!frame_sink) {
        SHA256_Update_VideoParameters(&sha256_ctx, *raw);
      }

      if (!output_file.empty()) {
        switch (raw->fourcc) {
          case make_fourcc('N', 'V', '1', '2'):
            raw_video_writer.WriteNv12(
                raw->primary_width_pixels, raw->primary_height_pixels,
                raw->primary_line_stride_bytes,
                buffer.base() + packet.start_offset + raw->primary_start_offset,
                raw->secondary_start_offset - raw->primary_start_offset);
            break;
          default:
            Exit("write to file only implemented for NV12");
        }
      }

      // PTS values are separately verified by use_h264_decoder_test since it'll
      // be nice to know separately if they're broken and how vs. frame format
      // and frame pixel data being broken, especially if there's just one
      // broken run that can't easily be reproduced.
      if (timestamps_out) {
        timestamps_out->emplace_back(
            std::make_pair(packet.has_timestamp_ish, packet.timestamp_ish));
      }

      if (!frame_sink) {
        switch (raw->fourcc) {
          case make_fourcc('N', 'V', '1', '2'): {
            // Y
            uint8_t* y_src =
                buffer.base() + packet.start_offset + raw->primary_start_offset;
            for (uint32_t y_iter = 0; y_iter < raw->primary_height_pixels;
                 y_iter++) {
              SHA256_Update(&sha256_ctx, y_src, raw->primary_width_pixels);
              y_src += raw->primary_line_stride_bytes;
            }
            // UV
            uint8_t* uv_src = buffer.base() + packet.start_offset +
                              raw->secondary_start_offset;
            for (uint32_t uv_iter = 0; uv_iter < raw->primary_height_pixels / 2;
                 uv_iter++) {
              // NV12 requires eacy UV line be same width as a Y line, and
              // same stride as a Y line.
              SHA256_Update(&sha256_ctx, uv_src, raw->primary_width_pixels);
              uv_src += raw->primary_line_stride_bytes;
            }
            break;
          }
          case make_fourcc('Y', 'V', '1', '2'): {
            // Y
            SHA256_Update_VideoPlane(
                &sha256_ctx,
                /*start=*/buffer.base() + packet.start_offset +
                    raw->primary_start_offset,
                raw->primary_width_pixels, raw->primary_line_stride_bytes,
                raw->primary_height_pixels);

            // V
            SHA256_Update_VideoPlane(
                &sha256_ctx,
                /*start=*/buffer.base() + packet.start_offset +
                    raw->secondary_start_offset,
                raw->secondary_width_pixels, raw->secondary_line_stride_bytes,
                raw->secondary_height_pixels);

            // U
            SHA256_Update_VideoPlane(
                &sha256_ctx,
                /*start=*/buffer.base() + packet.start_offset +
                    raw->tertiary_start_offset,
                raw->secondary_width_pixels, raw->secondary_line_stride_bytes,
                raw->secondary_height_pixels);

            break;
          }
          default:
            Exit("SHA frame hashing only implemented for NV12 and YV12");
        }
      }

      if (frame_sink) {
        async::PostTask(
            main_loop->dispatcher(),
            [frame_sink,
             image_id = packet.header.packet_index + kFirstValidImageId,
             &vmo = buffer.vmo(),
             vmo_offset = buffer.vmo_offset() + packet.start_offset +
                          raw->primary_start_offset,
             config, cleanup = std::move(cleanup)]() mutable {
              frame_sink->PutFrame(image_id, vmo, vmo_offset, config,
                                   [cleanup = std::move(cleanup)] {
                                     // The ~cleanup can run on any thread (the
                                     // current thread is main_loop's thread),
                                     // and codec_client is ok with that
                                     // (because it switches over to |loop|'s
                                     // thread before sending a Codec message).
                                     //
                                     // ~cleanup
                                   });
            });
      }
      // If we didn't std::move(cleanup) before here, then ~cleanup runs here.
    }
  end_of_output:;
    if (!SHA256_Final(md_out, &sha256_ctx)) {
      assert(false);
    }
    printf("output thread done\n");
    // output thread done
    // ~raw_video_writer
  });

  // decode for a bit...  in_thread, loop, out_thread, and the codec itself are
  // taking care of it.

  // First wait for the input thread to be done feeding input data.  Before the
  // in_thread terminates, it'll have sent in a last empty EOS input buffer.
  VLOGF("before in_thread->join()...\n");
  in_thread->join();
  VLOGF("after in_thread->join()\n");

  // The EOS queued as an input buffer should cause the codec to output an EOS
  // output buffer, at which point out_thread should terminate, after it has
  // finalized the output file.
  VLOGF("before out_thread->join()...\n");
  out_thread->join();
  VLOGF("after out_thread->join()\n");

  // We wait for frame_sink to return all the frames for these reasons:
  //   * As of this writing, some noisy-in-the-log things can happen in Scenic
  //     if we don't.
  //   * We don't want to cancel display of any frames, because we want to see
  //     the frames on the screen.
  //   * We don't want the |cleanup| to run after codec_client is gone since the
  //     |cleanup| calls codec_client.
  //   * It's easier to grok if activity started by use_h264_decoder() is done
  //     by the time use_h264_decoder() returns, given use_h264_decoder()'s role
  //     as an overall sequencer.
  if (frame_sink) {
    // TODO(dustingreen): Make this less hacky - currently we sleep 10 seconds
    // to give Scenic a chance to display anything.  Despite this, we don't see
    // many frames displayed - TBD why not (it's not the cost of SW-based
    // YUV-to-RGB conversion, since removing most of that cost doesn't change
    // # of frames displayed).
    FXL_LOG(INFO) << "sleeping 10 seconds...";
    zx_nanosleep(zx_deadline_after(ZX_SEC(10)));
    FXL_LOG(INFO) << "done sleeping.";

    std::mutex frames_done_lock;
    bool frames_done = false;
    std::condition_variable frames_done_condition;
    fit::closure on_frames_returned = [&frames_done_lock, &frames_done,
                                       &frames_done_condition] {
      {  // scope lock
        std::lock_guard<std::mutex> lock(frames_done_lock);
        frames_done = true;
        // The notify while still under the lock prevents any possibility of
        // frames_done_condition being gone too soon.
        frames_done_condition.notify_all();
        // Don't touch the captures beyond this point.
      }  // ~lock
    };
    async::PostTask(main_loop->dispatcher(),
                    [frame_sink, on_frames_returned =
                                     std::move(on_frames_returned)]() mutable {
                      frame_sink->PutEndOfStreamThenWaitForFramesReturnedAsync(
                          std::move(on_frames_returned));
                    });
    // The just-posted wait will set frames_done using the main_loop_'s thread,
    // which is not this thread.
    FXL_LOG(INFO) << "waiting for all frames to be returned from Scenic...";
    {  // scope lock
      std::unique_lock<std::mutex> lock(frames_done_lock);
      while (!frames_done) {
        frames_done_condition.wait(lock);
      }
    }  // ~lock
    FXL_LOG(INFO) << "all frames have been returned from Scenic";
    // Now we know that there are zero frames in frame_sink, including zero
    // frame cleanup(s) in-flight (in the sense of a pending/running cleanup
    // that's touching codec_client to post any new work.  Work already posted
    // via codec_client can still be in flight.  See below.)
  }

  // Because CodecClient posted work to the loop which captured the CodecClient
  // as "this", it's important that we ensure that all such work is done trying
  // to run before we delete CodecClient.  We need to know that the work posted
  // using PostSerial() won't be trying to touch the channel or pointers that
  // are owned by CodecClient before we close the channel or destruct
  // CodecClient (which happens before ~loop).
  //
  // We call loop.Quit();loop.JoinThreads(); before codec_client.Stop() because
  // there can be at least a RecycleOutputPacket() still working its way toward
  // the Codec (via the loop) at this point, so doing
  // loop.Quit();loop.JoinThreads(); first avoids potential FIDL message send
  // errors.  We're done decoding so we don't care whether any remaining queued
  // messages toward the codec actually reach the codec.
  //
  // We use loop.Quit();loop.JoinThreads(); instead of loop.Shutdown() because
  // we don't want the Shutdown() side-effect of failing the channel bindings.
  // The Shutdown() will happen later.
  //
  // By ensuring that the loop is done running code before closing the channel
  // (or loop.Shutdown()), we can close the channel cleanly and avoid mitigation
  // of expected normal channel closure (or loop.Shutdown()) in any code that
  // runs on the loop.  This way, unexpected channel failure is the only case to
  // worry about.
  VLOGF("before loop.Quit()\n");
  loop.Quit();
  VLOGF("before loop.JoinThreads()...\n");
  loop.JoinThreads();
  VLOGF("after loop.JoinThreads()\n");

  // Close the channel explicitly (just so we can more easily print messages
  // before and after vs. ~codec_client).
  VLOGF("before codec_client stop...\n");
  codec_client.Stop();
  VLOGF("after codec_client stop.\n");

  // loop.Shutdown() the rest of the way explicitly (just so we can more easily
  // print messages before and after vs. ~loop).  If we did this before
  // codec_client.Stop() it would cause the channel bindings to fail because
  // async waits are failed as cancelled during Shutdown().
  VLOGF("before loop.Shutdown()...\n");
  loop.Shutdown();
  VLOGF("after loop.Shutdown()\n");

  // The FIDL loop isn't running any more and the channels are closed.  There
  // are no other threads left that were started by this function.  We can just
  // delete stuff now.

  // success
  // ~codec_client
  // ~loop
  // ~codec_factory
  return;
}

void use_h264_decoder(async::Loop* main_loop,
                      fuchsia::mediacodec::CodecFactoryPtr codec_factory,
                      const std::string& input_file,
                      const std::string& output_file,
                      uint8_t md_out[SHA256_DIGEST_LENGTH],
                      std::vector<std::pair<bool, uint64_t>>* timestamps_out,
                      FrameSink* frame_sink) {
  use_video_decoder(main_loop, std::move(codec_factory), Format::kH264,
                    input_file, output_file, md_out, timestamps_out,
                    frame_sink);
}

void use_vp9_decoder(async::Loop* main_loop,
                     fuchsia::mediacodec::CodecFactoryPtr codec_factory,
                     const std::string& input_file,
                     const std::string& output_file,
                     uint8_t md_out[SHA256_DIGEST_LENGTH],
                     std::vector<std::pair<bool, uint64_t>>* timestamps_out,
                     FrameSink* frame_sink) {
  use_video_decoder(main_loop, std::move(codec_factory), Format::kVp9,
                    input_file, output_file, md_out, timestamps_out,
                    frame_sink);
}
