// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef SRC_MEDIA_CODEC_CODECS_VAAPI_LOCAL_SINGLE_CODEC_FACTORY_H_
#define SRC_MEDIA_CODEC_CODECS_VAAPI_LOCAL_SINGLE_CODEC_FACTORY_H_

#include <fuchsia/mediacodec/cpp/fidl.h>
#include <lib/fidl/cpp/binding.h>
#include <lib/media/codec_impl/codec_adapter.h>
#include <lib/media/codec_impl/codec_admission_control.h>
#include <lib/media/codec_impl/codec_diagnostics.h>
#include <lib/media/codec_impl/codec_impl.h>
#include <lib/syslog/cpp/macros.h>
#include <threads.h>

#include "vaapi_utils.h"

// Marker type to specify these is no adapter to serve a request.
class NoAdapter {};

// Prepares a single codec for the codec runner and then requests drop of self.
// If a software can only provide an encoder or decoder, the other should be
// assigned NoAdapter in the template arguments, e.g.:
//   LocalSingleCodecFactory<CodecAdapterFfmpeg, NoAdapter>
template <typename DecoderAdapter, typename EncoderAdapter>
class LocalSingleCodecFactory : public fuchsia::mediacodec::CodecFactory {
 public:
  LocalSingleCodecFactory(async_dispatcher_t* fidl_dispatcher,
                          fidl::InterfaceHandle<fuchsia::sysmem::Allocator> sysmem,
                          fidl::InterfaceRequest<CodecFactory> request,
                          fit::function<void(std::unique_ptr<CodecImpl>)> factory_done_callback,
                          CodecAdmissionControl* codec_admission_control,
                          fit::function<void(zx_status_t)> error_handler,
                          CodecDiagnostics* codec_diagnostics = nullptr)
      : fidl_dispatcher_(fidl_dispatcher),
        sysmem_(std::move(sysmem)),
        binding_(this),
        factory_done_callback_(std::move(factory_done_callback)),
        codec_admission_control_(codec_admission_control),
        codec_diagnostics_(codec_diagnostics) {
    binding_.set_error_handler(std::move(error_handler));
    zx_status_t status = binding_.Bind(std::move(request), fidl_dispatcher);
    ZX_ASSERT(status == ZX_OK);

    binding_.events().OnCodecList(GetDeprecatedCodecList());
  }

  void GetDetailedCodecDescriptions(GetDetailedCodecDescriptionsCallback callback) override {
    fuchsia::mediacodec::CodecFactoryGetDetailedCodecDescriptionsResponse response;
    response.set_codecs(GetCodecDescriptions());
    callback(std::move(response));
  }

  void CreateDecoder(
      fuchsia::mediacodec::CreateDecoder_Params decoder_params,
      fidl::InterfaceRequest<fuchsia::media::StreamProcessor> decoder_request) override {
    VendCodecAdapter<DecoderAdapter>(std::move(decoder_params), std::move(decoder_request),
                                     std::move(lifetime_tracking_));
    ZX_DEBUG_ASSERT(lifetime_tracking_.empty());
  }

  void CreateEncoder(
      fuchsia::mediacodec::CreateEncoder_Params encoder_params,
      fidl::InterfaceRequest<fuchsia::media::StreamProcessor> encoder_request) override {
    VendCodecAdapter<EncoderAdapter>(std::move(encoder_params), std::move(encoder_request),
                                     std::move(lifetime_tracking_));
    ZX_DEBUG_ASSERT(lifetime_tracking_.empty());
  }

  void AttachLifetimeTracking(zx::eventpair codec_end) override {
    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) {
      binding_.Close(ZX_ERR_BAD_STATE);
      // This call will delete this, and will Quit() the loop of the isolate so the isolate will
      // exit shortly.
      factory_done_callback_(nullptr);
      return;
    }
    lifetime_tracking_.emplace_back(std::move(codec_end));
  }

 private:
  template <typename Adapter, typename Params>
  void VendCodecAdapter(Params params,
                        fidl::InterfaceRequest<fuchsia::media::StreamProcessor> codec_request,
                        std::vector<zx::eventpair> lifetime_tracking_eventpair) {
    // Ignore channel errors (e.g. PEER_CLOSED) after this point, because this channel has served
    // its purpose. Otherwise the error handler could tear down the loop before the codec was
    // finished being added.
    binding_.set_error_handler([](auto) {});
    codec_admission_control_->TryAddCodec(
        /*multi_instance=*/true,
        [this, params = std::move(params), codec_request = std::move(codec_request),
         lifetime_tracking_eventpair = std::move(lifetime_tracking_eventpair)](
            std::unique_ptr<CodecAdmission> codec_admission) mutable {
          if (!codec_admission) {
            // ~codec_request closes channel.
            return;
          }

          if (!sysmem_) {
            FX_LOGS(WARNING) << "VendCodecAdapter() only meant to be used once per "
                                "LocalSingleCodecFactory\n";
            // ~codec_request closes channel.
            return;
          }

          auto codec_impl = std::make_unique<CodecImpl>(
              std::move(sysmem_), std::move(codec_admission), fidl_dispatcher_, thrd_current(),
              std::move(params), std::move(codec_request));

          codec_impl->SetLifetimeTracking(std::move(lifetime_tracking_eventpair));

          codec_impl->SetCoreCodecAdapter(
              std::make_unique<Adapter>(codec_impl->lock(), codec_impl.get()));

          if (codec_diagnostics_) {
            codec_impl->SetCodecDiagnostics(codec_diagnostics_);
          }

          // This hands off the codec impl to the creator of |this| and is
          // expected to |~this|.
          factory_done_callback_(std::move(codec_impl));
        });
  }

  template <>
  void VendCodecAdapter<NoAdapter, fuchsia::mediacodec::CreateDecoder_Params>(
      fuchsia::mediacodec::CreateDecoder_Params params,
      fidl::InterfaceRequest<fuchsia::media::StreamProcessor> codec_request,
      std::vector<zx::eventpair> lifetime_tracking_eventpair) {
    // No adapter.
    // ~codec_request.
    // ~lifetime_tracking_eventpair
  }

  template <>
  void VendCodecAdapter<NoAdapter, fuchsia::mediacodec::CreateEncoder_Params>(
      fuchsia::mediacodec::CreateEncoder_Params params,
      fidl::InterfaceRequest<fuchsia::media::StreamProcessor> codec_request,
      std::vector<zx::eventpair> lifetime_tracking_eventpair) {
    // No adapter.
    // ~codec_request.
    // ~lifetime_tracking_eventpair
  }

  async_dispatcher_t* fidl_dispatcher_;
  fidl::InterfaceHandle<fuchsia::sysmem::Allocator> sysmem_;
  fidl::Binding<CodecFactory, LocalSingleCodecFactory*> binding_;
  // Returns the codec implementation and requests drop of self.
  fit::function<void(std::unique_ptr<CodecImpl>)> factory_done_callback_;
  CodecAdmissionControl* codec_admission_control_;
  std::vector<zx::eventpair> lifetime_tracking_;
  CodecDiagnostics* codec_diagnostics_;
};

#endif  // SRC_MEDIA_CODEC_CODECS_VAAPI_LOCAL_SINGLE_CODEC_FACTORY_H_
