blob: c1839010784dacf9b5edaf1763cba0872c286588 [file] [log] [blame]
// 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 "so_entry_point.h"
// SoftOMXComponent.h assumes that <log/log.h> is included first.
#include <log/log.h>
#include <media/stagefright/omx/SoftOMXComponent.h>
#include <lib/fit/defer.h>
// We intentionally don't have a "using namespace android;" because this is an
// adapter layer and we want to make clear what's raw OMX and what's android
// stuff that we're hiding from the caller of the entry point defined at the
// bottom of this file.
// In android sources, the per-OMX-codec common entry point signature isn't in
// any header file, so we just declare it here. We're using this symbol locally
// within each per-codec binary we build for Fuchsia, and wrapping it with an
// extern "C" shared_library entry point that doesn't return a C++ object. Only
// the latter is exported from the per-android-codec fuchsia shared lib.
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks, OMX_PTR appData,
OMX_COMPONENTTYPE **component);
namespace {
// A pointer to this function gets used as an OMX_COMPONENTTYPE.ComponentDeInit.
OMX_ERRORTYPE ComponentDeInit(OMX_IN OMX_HANDLETYPE hComponent) {
auto *me = (android::SoftOMXComponent *)((OMX_COMPONENTTYPE *)hComponent)
->pComponentPrivate;
me->prepareForDestruction();
me->decStrong(reinterpret_cast<void *>(ComponentDeInit));
// It's important that by this point any threads that were created by
// SimpleSoftOMXComponent or by the lower-layer codec core (if any) are
// totally done running any code of the present shared library, as the caller
// of this function will _un-load the code_ of this shared library.
return OMX_ErrorNone;
}
} // namespace
extern "C" {
// This interface is not meant to be Fuchsia-wide for SW codecs. For that, see
// the Codec FIDL interface defined elsewhere. This commonality of interface
// here is just for building and loading various SW codecs from the android
// sources.
//
// Sets *component to nullptr if create fails, or to non-nullptr if create
// succeeds.
void entrypoint_createSoftOMXComponent(const char *name,
const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData,
OMX_COMPONENTTYPE **component) {
// default to reporting failure uness we get far enough
*component = nullptr;
// We use the android::sp to ensure that every path from here forward will
// have at least one strong reference on the SoftOMXComponent (added here if
// not nullptr), including error paths.
android::sp<android::SoftOMXComponent> component_cpp =
createSoftOMXComponent(name, callbacks, appData, component);
if (!component_cpp) {
// TODO: can we log an error somewhere and/or return richer error info from
// a shared_library entry point in Fuchsia-standard ways?
// assert that we are reporting failure:
assert(!(*component));
return;
}
// Unfortunately the android code doesn't take advantage of
// RefBase::onLastStrongRef(), and doesn't seem worth making a wrapper that
// does just for the benefit of this source file.
//
// unless cancelled
auto pfd = fit::defer(
[&component_cpp]() { component_cpp->prepareForDestruction(); });
if (OMX_ErrorNone != component_cpp->initCheck()) {
assert(!(*component));
return;
}
if (static_cast<OMX_PTR>(component_cpp.get()) !=
(*component)->pComponentPrivate) {
// The android code changed to no longer stash SoftOMXComponent* where this
// code expects. At the moment there doesn't seem to be any good way to
// wrap more thoroughly that doesn't also risk getting broken by android
// changes, so if the stashing has changed in android code, fail the create.
// assert that we are reporting failure:
assert(!(*component));
// ~pfd
// ~component_cpp
return;
}
if ((*component)->ComponentDeInit) {
// The android code has changed to fill out this function pointer. Without
// a more thourough wrapping, which would itself be subject to breakage by
// android changes that add more function pointers (to callbacks and/or to
// component), we have no great place to stash the value of ComponentDeInit.
// An alternative would be for the present entry point to fill out a wrapper
// of OMX_COMPONENTTYPE that just points to an OMX_COMPONENTTYPE, but the
// benefit/cost of that doesn't seem high enough, at least for now. So if
// android code changed to start using this function pointer, fail the
// create.
// assert that we are reporting failure:
assert(!(*component));
// ~pfd
// ~component_cpp
return;
}
// This ComponentDeInit will call prepareForDestruction().
(*component)->ComponentDeInit = ComponentDeInit;
// Don't call prepareForDestruction() during ~pfd.
pfd.cancel();
// Prevent ~component_cpp from deleting the codec. This ref will be removed
// by ComponentDeInit, so may as well use that as the void* on the ref.
component_cpp->incStrong(reinterpret_cast<void *>(ComponentDeInit));
// The non-use of setLibHandle() and libHandle() is intentional, since the
// loading and un-loading of the shared library is handled in a layer above
// that doesn't see SoftOMXComponent.
return;
}
// This function is only used when linked as a static lib, for debug-cycle
// purposes only.
void direct_createSoftOMXComponent(const char *name,
const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData,
OMX_COMPONENTTYPE **component) {
entrypoint_createSoftOMXComponent(name, callbacks, appData, component);
}
} // extern "C"