245 lines
7.5 KiB
C++
245 lines
7.5 KiB
C++
|
/*
|
||
|
* Copyright 2018 The Android Open Source Project
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
|
||
|
#define LOG_TAG "GoldfishOMXPlugin"
|
||
|
#include "GoldfishOMXPlugin.h"
|
||
|
|
||
|
//#define LOG_NDEBUG 0
|
||
|
#include <vector>
|
||
|
|
||
|
#include <cutils/properties.h>
|
||
|
#include <log/log.h>
|
||
|
|
||
|
#include "GoldfishOMXComponent.h"
|
||
|
|
||
|
#include <media/stagefright/foundation/ADebug.h>
|
||
|
#include <media/stagefright/foundation/AString.h>
|
||
|
|
||
|
#include <dlfcn.h>
|
||
|
|
||
|
namespace android {
|
||
|
|
||
|
OMXPluginBase *createOMXPlugin() {
|
||
|
ALOGD("called createOMXPlugin for Goldfish");
|
||
|
return new GoldfishOMXPlugin;
|
||
|
}
|
||
|
|
||
|
// Each component's name should have it's own feature flag in order to toggle
|
||
|
// individual codecs
|
||
|
struct GoldfishComponent {
|
||
|
const char *mName;
|
||
|
const char *mLibNameSuffix;
|
||
|
const char *mRole;
|
||
|
};
|
||
|
|
||
|
static bool useOmxCodecs() {
|
||
|
char propValue[PROP_VALUE_MAX];
|
||
|
AString prop = "debug.stagefright.ccodec";
|
||
|
bool myret = property_get(prop.c_str(), propValue, "") > 0 &&
|
||
|
strcmp("0", propValue) == 0;
|
||
|
if (myret) {
|
||
|
ALOGD("%s %d found prop %s val %s", __func__, __LINE__, prop.c_str(), propValue);
|
||
|
}
|
||
|
return myret;
|
||
|
}
|
||
|
|
||
|
// We have a property set indicating whether to use the host side codec
|
||
|
// or not (ro.boot.qemu.hwcodec.<mLibNameSuffix>).
|
||
|
static std::string BuildHWCodecPropName(const char *libname) {
|
||
|
using namespace std::literals::string_literals;
|
||
|
return "ro.boot.qemu.hwcodec."s + libname;
|
||
|
}
|
||
|
|
||
|
static bool useGoogleGoldfishComponentInstance(const char* libname) {
|
||
|
const std::string propName = BuildHWCodecPropName(libname);
|
||
|
char propValue[PROP_VALUE_MAX];
|
||
|
|
||
|
bool myret = property_get(propName.c_str(), propValue, "") > 0 &&
|
||
|
strcmp("1", propValue) == 0;
|
||
|
if (myret) {
|
||
|
ALOGD("%s %d found prop %s val %s", __func__, __LINE__, propName.c_str(), propValue);
|
||
|
}
|
||
|
return myret;
|
||
|
}
|
||
|
|
||
|
static bool useAndroidGoldfishComponentInstance(const char* libname) {
|
||
|
const std::string propName = BuildHWCodecPropName(libname);
|
||
|
char propValue[PROP_VALUE_MAX];
|
||
|
|
||
|
bool myret = property_get(propName.c_str(), propValue, "") > 0 &&
|
||
|
strcmp("2", propValue) == 0;
|
||
|
if (myret) {
|
||
|
ALOGD("%s %d found prop %s val %s", __func__, __LINE__, propName.c_str(), propValue);
|
||
|
}
|
||
|
return myret;
|
||
|
}
|
||
|
|
||
|
static const GoldfishComponent kComponents[] = {
|
||
|
{"OMX.google.goldfish.vp8.decoder", "vpxdec", "video_decoder.vp8"},
|
||
|
{"OMX.google.goldfish.vp9.decoder", "vpxdec", "video_decoder.vp9"},
|
||
|
{"OMX.google.goldfish.h264.decoder", "avcdec", "video_decoder.avc"},
|
||
|
{"OMX.android.goldfish.vp8.decoder", "vpxdec", "video_decoder.vp8"},
|
||
|
{"OMX.android.goldfish.vp9.decoder", "vpxdec", "video_decoder.vp9"},
|
||
|
{"OMX.android.goldfish.h264.decoder", "avcdec", "video_decoder.avc"},
|
||
|
};
|
||
|
|
||
|
static std::vector<GoldfishComponent> kActiveComponents;
|
||
|
|
||
|
static const size_t kNumComponents =
|
||
|
sizeof(kComponents) / sizeof(kComponents[0]);
|
||
|
|
||
|
GoldfishOMXPlugin::GoldfishOMXPlugin() {
|
||
|
if (useOmxCodecs()) {
|
||
|
for (int i = 0; i < kNumComponents; ++i) {
|
||
|
if (!strncmp("OMX.google", kComponents[i].mName, 10) &&
|
||
|
useGoogleGoldfishComponentInstance(
|
||
|
kComponents[i].mLibNameSuffix)) {
|
||
|
ALOGD("found and use kComponents[i].name %s",
|
||
|
kComponents[i].mName);
|
||
|
kActiveComponents.push_back(kComponents[i]);
|
||
|
} else if (!strncmp("OMX.android", kComponents[i].mName, 11) &&
|
||
|
useAndroidGoldfishComponentInstance(
|
||
|
kComponents[i].mLibNameSuffix)) {
|
||
|
ALOGD("found and use kComponents[i].name %s",
|
||
|
kComponents[i].mName);
|
||
|
kActiveComponents.push_back(kComponents[i]);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
OMX_ERRORTYPE GoldfishOMXPlugin::makeComponentInstance(
|
||
|
const char *name,
|
||
|
const OMX_CALLBACKTYPE *callbacks,
|
||
|
OMX_PTR appData,
|
||
|
OMX_COMPONENTTYPE **component) {
|
||
|
ALOGI("makeComponentInstance '%s'", name);
|
||
|
|
||
|
for (size_t i = 0; i < kActiveComponents.size(); ++i) {
|
||
|
if (strcmp(name, kActiveComponents[i].mName)) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
AString libName;
|
||
|
AString ldsExport;
|
||
|
libName = "libstagefright_goldfish_";
|
||
|
ldsExport = "_Z26createGoldfishOMXComponentPKcPK16OMX_CALLBACKTYPEPvPP17OMX_COMPONENTTYPE";
|
||
|
ALOGI("Using goldfish codec for '%s'", kActiveComponents[i].mLibNameSuffix);
|
||
|
|
||
|
libName.append(kActiveComponents[i].mLibNameSuffix);
|
||
|
libName.append(".so");
|
||
|
|
||
|
void *libHandle = dlopen(libName.c_str(), RTLD_NOW|RTLD_NODELETE);
|
||
|
|
||
|
if (libHandle == NULL) {
|
||
|
ALOGE("unable to dlopen %s: %s", libName.c_str(), dlerror());
|
||
|
|
||
|
return OMX_ErrorComponentNotFound;
|
||
|
}
|
||
|
|
||
|
typedef GoldfishOMXComponent *(*CreateGoldfishOMXComponentFunc)(
|
||
|
const char *, const OMX_CALLBACKTYPE *,
|
||
|
OMX_PTR, OMX_COMPONENTTYPE **);
|
||
|
|
||
|
CreateGoldfishOMXComponentFunc createGoldfishOMXComponent =
|
||
|
(CreateGoldfishOMXComponentFunc)dlsym(
|
||
|
libHandle,
|
||
|
ldsExport.c_str()
|
||
|
);
|
||
|
|
||
|
if (createGoldfishOMXComponent == NULL) {
|
||
|
ALOGE("unable to create component for %s", libName.c_str());
|
||
|
dlclose(libHandle);
|
||
|
libHandle = NULL;
|
||
|
|
||
|
return OMX_ErrorComponentNotFound;
|
||
|
}
|
||
|
|
||
|
sp<GoldfishOMXComponent> codec =
|
||
|
(*createGoldfishOMXComponent)(name, callbacks, appData, component);
|
||
|
|
||
|
if (codec == NULL) {
|
||
|
dlclose(libHandle);
|
||
|
libHandle = NULL;
|
||
|
|
||
|
return OMX_ErrorInsufficientResources;
|
||
|
}
|
||
|
|
||
|
OMX_ERRORTYPE err = codec->initCheck();
|
||
|
if (err != OMX_ErrorNone) {
|
||
|
dlclose(libHandle);
|
||
|
libHandle = NULL;
|
||
|
|
||
|
return err;
|
||
|
}
|
||
|
|
||
|
codec->incStrong(this);
|
||
|
codec->setLibHandle(libHandle);
|
||
|
|
||
|
return OMX_ErrorNone;
|
||
|
}
|
||
|
|
||
|
return OMX_ErrorInvalidComponentName;
|
||
|
}
|
||
|
|
||
|
OMX_ERRORTYPE GoldfishOMXPlugin::destroyComponentInstance(
|
||
|
OMX_COMPONENTTYPE *component) {
|
||
|
GoldfishOMXComponent *me =
|
||
|
(GoldfishOMXComponent *)
|
||
|
((OMX_COMPONENTTYPE *)component)->pComponentPrivate;
|
||
|
|
||
|
me->prepareForDestruction();
|
||
|
|
||
|
CHECK_EQ(me->getStrongCount(), 1);
|
||
|
me->decStrong(this);
|
||
|
me = NULL;
|
||
|
|
||
|
return OMX_ErrorNone;
|
||
|
}
|
||
|
|
||
|
OMX_ERRORTYPE GoldfishOMXPlugin::enumerateComponents(
|
||
|
OMX_STRING name,
|
||
|
size_t /* size */,
|
||
|
OMX_U32 index) {
|
||
|
if (index >= kActiveComponents.size()) {
|
||
|
return OMX_ErrorNoMore;
|
||
|
}
|
||
|
|
||
|
ALOGD("enumerate %s component", kActiveComponents[index].mName);
|
||
|
strcpy(name, kActiveComponents[index].mName);
|
||
|
|
||
|
return OMX_ErrorNone;
|
||
|
}
|
||
|
|
||
|
OMX_ERRORTYPE GoldfishOMXPlugin::getRolesOfComponent(
|
||
|
const char *name,
|
||
|
Vector<String8> *roles) {
|
||
|
for (size_t i = 0; i < kActiveComponents.size(); ++i) {
|
||
|
if (strcmp(name, kActiveComponents[i].mName)) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
roles->clear();
|
||
|
roles->push(String8(kActiveComponents[i].mRole));
|
||
|
|
||
|
return OMX_ErrorNone;
|
||
|
}
|
||
|
|
||
|
return OMX_ErrorInvalidComponentName;
|
||
|
}
|
||
|
|
||
|
} // namespace android
|