blob: c8582f092c897799ab5e6787fe6cc088b64dd155 [file] [log] [blame]
// 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_