blob: e3dd0cfe3d01c6f95a95be4ff370125220682ebe [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 GARNET_BIN_MEDIA_CODECS_SW_CODEC_RUNNER_APP_H_
#define GARNET_BIN_MEDIA_CODECS_SW_CODEC_RUNNER_APP_H_
#include <memory>
#include <fuchsia/mediacodec/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/component/cpp/startup_context.h>
#include <lib/fidl/cpp/interface_request.h>
#include <src/lib/fxl/logging.h>
#include "local_single_codec_factory.h"
// If a software can only provide an encoder or decoder, the other should be
// assigned NoAdapter in the template arguments, e.g.:
// CodecRunnerApp<CodecAdapterFfmpeg, NoAdapter>
template <typename Decoder, typename Encoder>
class CodecRunnerApp {
public:
CodecRunnerApp()
: loop_(&kAsyncLoopConfigAttachToThread),
startup_context_(component::StartupContext::CreateFromStartupInfo()) {}
void Run() {
// Lives until after Loop.Run() which is fine since it is not referenced
// after Loop.Run().
auto codec_admission_control =
std::make_unique<CodecAdmissionControl>(loop_.dispatcher());
startup_context_->outgoing().deprecated_services()->AddService(
fidl::InterfaceRequestHandler<fuchsia::mediacodec::CodecFactory>(
[this, codec_admission_control = codec_admission_control.get()](
fidl::InterfaceRequest<fuchsia::mediacodec::CodecFactory>
request) {
// This runner only expects a single Local Codec Factory to ever
// be requested.
FXL_DCHECK(!codec_factory_);
startup_context_->outgoing()
.deprecated_services()
->RemoveService<fuchsia::mediacodec::CodecFactory>();
fidl::InterfaceHandle<fuchsia::sysmem::Allocator> sysmem;
startup_context_->ConnectToEnvironmentService(sysmem.NewRequest());
codec_factory_ =
std::make_unique<LocalSingleCodecFactory<Decoder, Encoder>>(
loop_.dispatcher(), std::move(sysmem), std::move(request),
[this](
std::unique_ptr<CodecImpl> created_codec_instance) {
// Own codec implementation and bind it.
codec_instance_ = std::move(created_codec_instance);
codec_instance_->BindAsync([this] {
// Drop codec implementation and close channel on
// error.
codec_instance_.reset();
});
// Drop factory and close factory channel.
codec_factory_.reset();
},
codec_admission_control,
[this](zx_status_t error) {
// Drop factory and close factory channel on error.
codec_factory_.reset();
});
}));
loop_.Run();
}
private:
async::Loop loop_;
std::unique_ptr<component::StartupContext> startup_context_;
std::unique_ptr<LocalSingleCodecFactory<Decoder, Encoder>> codec_factory_;
std::unique_ptr<CodecImpl> codec_instance_;
};
#endif // GARNET_BIN_MEDIA_CODECS_SW_CODEC_RUNNER_APP_H_