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

#include <lib/fidl/cpp/clone.h>
#include <lib/fit/function.h>
#include <lib/media/codec_impl/codec_admission_control.h>

#include <optional>

#include "codec_adapter_h264_multi.h"
#include "codec_adapter_mpeg2.h"
#include "codec_adapter_vp9.h"
#include "device_ctx.h"

namespace amlogic_decoder {

namespace {

struct CodecAdapterFactory {
  bool is_enabled;
  fuchsia::mediacodec::CodecDescription description;

  // This typedef is just for local readability here, not for use outside this
  // struct.
  using CreateFunction = fit::function<std::unique_ptr<CodecAdapter>(
      std::mutex& lock, CodecAdapterEvents*, DeviceCtx*)>;

  bool multi_instance;

  CreateFunction create;
};

// TODO(dustingreen): Fix up this list to correspond to what
// CodecImpl+AmlogicVideo can actually handle so far, once there's at least one
// format in that list.  For now this list is here to allow covering some
// LocalCodecFactory code.
const CodecAdapterFactory kCodecFactories[] = {
    {
        true,  // is_enabled
        fuchsia::mediacodec::CodecDescription{
            .codec_type = fuchsia::mediacodec::CodecType::DECODER,
            // TODO(dustingreen): See TODO comments on this field in
            // codec_common.fidl.
            .mime_type = "video/h264",

            // TODO(fxbug.dev/13483): Make more of these true by implementing in
            // CodecAdapterH264Multi.
            .can_stream_bytes_input = true,
            .can_find_start = false,
            .can_re_sync = false,
            .will_report_all_detected_errors = false,

            .is_hw = true,

            // TODO(dustingreen): Determine if this claim of "true" is actually
            // the case.
            .split_header_handling = true,
        },
        true,  // multi_instance
        [](std::mutex& lock, CodecAdapterEvents* events, DeviceCtx* device) {
          return std::make_unique<CodecAdapterH264Multi>(lock, events, device);
        },
    },
    {
        false,  // is_enabled
        fuchsia::mediacodec::CodecDescription{
            .codec_type = fuchsia::mediacodec::CodecType::DECODER,
            // TODO(dustingreen): See TODO comments on this field in
            // codec_common.fidl.
            .mime_type = "video/mpeg2",

            // TODO(dustingreen): Determine which of these can safely indicate
            // more capability.
            .can_stream_bytes_input = false,
            .can_find_start = false,
            .can_re_sync = false,
            .will_report_all_detected_errors = false,

            .is_hw = true,

            // TODO(dustingreen): Determine if this claim of "true" is actually
            // the case.
            .split_header_handling = true,
        },
        false,  // multi_instance
        [](std::mutex& lock, CodecAdapterEvents* events, DeviceCtx* device) {
          return std::make_unique<CodecAdapterMpeg2>(lock, events, device);
        },
    },
    {
        true,  // is_enabled
        fuchsia::mediacodec::CodecDescription{
            .codec_type = fuchsia::mediacodec::CodecType::DECODER,
            // TODO(dustingreen): See TODO comments on this field in
            // codec_common.fidl.
            .mime_type = "video/vp9",

            // TODO(dustingreen): Determine which of these can safely indicate
            // more capability.
            .can_stream_bytes_input = false,
            .can_find_start = false,
            .can_re_sync = false,
            .will_report_all_detected_errors = false,

            .is_hw = true,

            // TODO(dustingreen): Determine if this claim of "true" is actually
            // the case.
            .split_header_handling = true,
        },
        true,  // multi_instance
        [](std::mutex& lock, CodecAdapterEvents* events, DeviceCtx* device) {
          return std::make_unique<CodecAdapterVp9>(lock, events, device);
        },
    },
    {
        true,  // is_enabled
        fuchsia::mediacodec::CodecDescription{
            .codec_type = fuchsia::mediacodec::CodecType::DECODER,
            // TODO(dustingreen): See TODO comments on this field in
            // codec_common.fidl.
            .mime_type = "video/h264-multi",

            // TODO(dustingreen): Determine which of these can safely indicate
            // more capability.
            .can_stream_bytes_input = false,
            .can_find_start = false,
            .can_re_sync = false,
            .will_report_all_detected_errors = false,

            .is_hw = true,

            // TODO(dustingreen): Determine if this claim of "true" is actually
            // the case.
            .split_header_handling = true,
        },
        true,  // multi_instance
        [](std::mutex& lock, CodecAdapterEvents* events, DeviceCtx* device) {
          return std::make_unique<CodecAdapterH264Multi>(lock, events, device);
        },
    },
    {
        true,  // is_enabled
        fuchsia::mediacodec::CodecDescription{
            .codec_type = fuchsia::mediacodec::CodecType::DECODER,
            // TODO(dustingreen): See TODO comments on this field in
            // codec_common.fidl.
            .mime_type = "video/h264-multi/test/force-context-save-restore",

            // TODO(dustingreen): Determine which of these can safely indicate
            // more capability.
            .can_stream_bytes_input = false,
            .can_find_start = false,
            .can_re_sync = false,
            .will_report_all_detected_errors = false,

            .is_hw = true,

            // TODO(dustingreen): Determine if this claim of "true" is actually
            // the case.
            .split_header_handling = true,
        },
        true,  // multi_instance
        [](std::mutex& lock, CodecAdapterEvents* events, DeviceCtx* device) {
          auto decoder = std::make_unique<CodecAdapterH264Multi>(lock, events, device);
          AmlogicDecoderTestHooks test_hooks = {
              .force_context_save_restore = true,
          };
          decoder->set_test_hooks(test_hooks);
          return decoder;
        },
    },
    {
        true,  // is_enabled
        fuchsia::mediacodec::CodecDescription{
            .codec_type = fuchsia::mediacodec::CodecType::DECODER,
            // TODO(dustingreen): See TODO comments on this field in
            // codec_common.fidl.
            .mime_type = "video/vp9/test/force-context-save-restore",

            // TODO(dustingreen): Determine which of these can safely indicate
            // more capability.
            .can_stream_bytes_input = false,
            .can_find_start = false,
            .can_re_sync = false,
            .will_report_all_detected_errors = false,

            .is_hw = true,

            // TODO(dustingreen): Determine if this claim of "true" is actually
            // the case.
            .split_header_handling = true,
        },
        true,  // multi_instance
        [](std::mutex& lock, CodecAdapterEvents* events, DeviceCtx* device) {
          auto decoder = std::make_unique<CodecAdapterVp9>(lock, events, device);
          AmlogicDecoderTestHooks test_hooks = {
              .force_context_save_restore = true,
          };
          decoder->set_test_hooks(test_hooks);
          return decoder;
        },
    },
};

}  // namespace

// device - associated device.
LocalCodecFactory::LocalCodecFactory(DeviceCtx* device) : device_(device), factory_binding_(this) {
  // nothing else to do here
}

LocalCodecFactory::~LocalCodecFactory() {
  // We need ~factory_binding_ to run on shared_fidl_thread() else it's not safe
  // to un-bind unilaterally (without the channel closing).  Unless not bound in
  // the first place.
  ZX_DEBUG_ASSERT(thrd_current() == device_->driver()->shared_fidl_thread() ||
                  !factory_binding_.is_bound());

  // ~factory_binding_ here + fact that we're running on shared_fidl_thread()
  // (if Bind() previously called) means error_handler won't be running
  // concurrently with ~LocalCodecFactory and won't run after ~factory_binding_
  // here.
}

void LocalCodecFactory::SetErrorHandler(fit::closure error_handler) {
  ZX_DEBUG_ASSERT(!factory_binding_.is_bound());
  factory_binding_.set_error_handler(
      [this, error_handler = std::move(error_handler)](zx_status_t status) mutable {
        ZX_DEBUG_ASSERT(thrd_current() == device_->driver()->shared_fidl_thread());
        // This queues after the similar posting in CreateDecoder() (via
        // TryAddCodec()), so that LocalCodecFactory won't get deleted until
        // after previously-started TryAddCodec()s are done.
        device_->codec_admission_control()->PostAfterPreviouslyStartedClosesDone(
            [this, error_handler = std::move(error_handler)] {
              ZX_DEBUG_ASSERT(thrd_current() == device_->driver()->shared_fidl_thread());
              error_handler();
              // "this" is gone
            });
      });
  is_error_handler_set_ = true;
}

void LocalCodecFactory::Bind(zx::channel server_endpoint) {
  ZX_DEBUG_ASSERT(is_error_handler_set_);
  ZX_DEBUG_ASSERT(!factory_binding_.is_bound());

  // Go!  (immediately - if Bind() is called on IOCTL thread, this can result in
  // _immediate_ dispatching over on shared_fidl_thread()).
  factory_binding_.Bind(std::move(server_endpoint),
                        device_->driver()->shared_fidl_loop()->dispatcher());

  // All HW-accelerated local CodecFactory(s) must send OnCodecList()
  // immediately upon creation of the local CodecFactory.
  std::vector<fuchsia::mediacodec::CodecDescription> codec_descriptions;
  for (const CodecAdapterFactory& factory : kCodecFactories) {
    if (!factory.is_enabled) {
      continue;
    }
    codec_descriptions.push_back(fidl::Clone(factory.description));
  }
  factory_binding_.events().OnCodecList(std::move(codec_descriptions));
}

void LocalCodecFactory::CreateDecoder(
    fuchsia::mediacodec::CreateDecoder_Params video_decoder_params,
    ::fidl::InterfaceRequest<fuchsia::media::StreamProcessor> video_decoder) {
  if (!video_decoder_params.has_input_details()) {
    return;
  }

  if (!video_decoder_params.input_details().has_mime_type()) {
    // Without mime_type we cannot search for a decoder.
    return;
  }

  const CodecAdapterFactory* factory = nullptr;
  for (const CodecAdapterFactory& candidate_factory : kCodecFactories) {
    if (!candidate_factory.is_enabled) {
      continue;
    }
    if (candidate_factory.description.mime_type ==
        video_decoder_params.input_details().mime_type()) {
      factory = &candidate_factory;
      break;
    }
  }
  if (!factory) {
    // This shouldn't really happen since the main CodecFactory shouldn't be
    // asking this LocalCodecFactory for a codec fitting a description that's
    // not a description this factory previously delivered to the main
    // CodecFactory via OnCodecList().
    //
    // TODO(dustingreen): epitaph for video_decoder.
    //
    // ~video_decoder here will take care of closing the channel
    return;
  }

  // We also post to the same queue in the set_error_handler() lambda, so that
  // we know the LocalCodecFactory will remain alive until after this lambda
  // completes.
  //
  // The factory pointer remains valid for whole lifetime of this devhost
  // process.
  device_->codec_admission_control()->TryAddCodec(
      factory->multi_instance, [this, video_decoder_params = std::move(video_decoder_params),
                                video_decoder = std::move(video_decoder),
                                factory](std::unique_ptr<CodecAdmission> codec_admission) mutable {
        if (!codec_admission) {
          // We can't create another Codec presently.
          //
          // ~video_decoder will take care of closing the channel.
          return;
        }

        fidl::InterfaceHandle<fuchsia::sysmem::Allocator> sysmem =
            device_->video()->ConnectToSysmem();
        if (!sysmem) {
          return;
        }

        auto codec =
            std::make_unique<CodecImpl>(std::move(sysmem), std::move(codec_admission),
                                        device_->driver()->shared_fidl_loop()->dispatcher(),
                                        device_->driver()->shared_fidl_thread(),
                                        std::move(video_decoder_params), std::move(video_decoder));

        codec->SetLifetimeTracking(std::move(lifetime_tracking_));
        ZX_DEBUG_ASSERT(lifetime_tracking_.empty());

        codec->SetCodecMetrics(&device_->metrics());
        auto core_codec = factory->create(codec->lock(), codec.get(), device_);
        // Don't wait for CodecAdapter sub-class to call LogEvent().  Verify this is not
        // std::nullopt here, as any CodecAdapter sub-class in amlogic_video_decoder is allowed to
        // call LogEvent() and must override CoreCodecMetricsImplementation().
        ZX_DEBUG_ASSERT(core_codec->CoreCodecMetricsImplementation());
        codec->SetCoreCodecAdapter(std::move(core_codec));

        codec->SetCodecDiagnostics(&device_->diagnostics());

        device_->device_fidl()->BindCodecImpl(std::move(codec));
      });
}

void LocalCodecFactory::CreateEncoder(
    fuchsia::mediacodec::CreateEncoder_Params encoder_params,
    ::fidl::InterfaceRequest<fuchsia::media::StreamProcessor> encoder_request) {
  // We have no encoders to provide.
  lifetime_tracking_.clear();
  // ~encoder_request
}

void LocalCodecFactory::AttachLifetimeTracking(zx::eventpair codec_end) {
  ZX_DEBUG_ASSERT(lifetime_tracking_.size() <=
                  fuchsia::mediacodec::CODEC_FACTORY_LIFETIME_TRACKING_EVENTPAIR_PER_CREATE_MAX);
  if (lifetime_tracking_.size() >=
      fuchsia::mediacodec::CODEC_FACTORY_LIFETIME_TRACKING_EVENTPAIR_PER_CREATE_MAX) {
    factory_binding_.Close(ZX_ERR_BAD_STATE);
    device_->device_fidl()->DeleteFactory(this);
    return;
  }
  lifetime_tracking_.emplace_back(std::move(codec_end));
}

}  // namespace amlogic_decoder
