1 /*
2  * Copyright 2018, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "StagefrightPluginLoader"
19 #include <utils/Log.h>
20 
21 #include <android-base/properties.h>
22 #include <dlfcn.h>
23 
24 #include "StagefrightPluginLoader.h"
25 
26 namespace android {
27 
28 /* static */ Mutex StagefrightPluginLoader::sMutex;
29 /* static */ std::unique_ptr<StagefrightPluginLoader> StagefrightPluginLoader::sInstance;
30 
31 namespace /* unnamed */ {
32 
33 constexpr const char kCCodecPluginPath[] = "libsfplugin_ccodec.so";
34 
35 }  // unnamed namespace
36 
StagefrightPluginLoader(const char * libPath)37 StagefrightPluginLoader::StagefrightPluginLoader(const char *libPath) {
38     if (android::base::GetIntProperty("debug.stagefright.ccodec", 1) == 0) {
39         ALOGD("CCodec is disabled.");
40         return;
41     }
42     mLibHandle = dlopen(libPath, RTLD_NOW | RTLD_NODELETE);
43     if (mLibHandle == nullptr) {
44         ALOGD("Failed to load library: %s (%s)", libPath, dlerror());
45         return;
46     }
47     mCreateCodec = (CodecBase::CreateCodecFunc)dlsym(mLibHandle, "CreateCodec");
48     if (mCreateCodec == nullptr) {
49         ALOGD("Failed to find symbol: CreateCodec (%s)", dlerror());
50     }
51     mCreateBuilder = (MediaCodecListBuilderBase::CreateBuilderFunc)dlsym(
52             mLibHandle, "CreateBuilder");
53     if (mCreateBuilder == nullptr) {
54         ALOGD("Failed to find symbol: CreateBuilder (%s)", dlerror());
55     }
56     mCreateInputSurface = (CodecBase::CreateInputSurfaceFunc)dlsym(
57             mLibHandle, "CreateInputSurface");
58     if (mCreateInputSurface == nullptr) {
59         ALOGD("Failed to find symbol: CreateInputSurface (%s)", dlerror());
60     }
61 }
62 
~StagefrightPluginLoader()63 StagefrightPluginLoader::~StagefrightPluginLoader() {
64     if (mLibHandle != nullptr) {
65         ALOGV("Closing handle");
66         dlclose(mLibHandle);
67     }
68 }
69 
createCodec()70 CodecBase *StagefrightPluginLoader::createCodec() {
71     if (mLibHandle == nullptr || mCreateCodec == nullptr) {
72         ALOGD("Handle or CreateCodec symbol is null");
73         return nullptr;
74     }
75     return mCreateCodec();
76 }
77 
createBuilder()78 MediaCodecListBuilderBase *StagefrightPluginLoader::createBuilder() {
79     if (mLibHandle == nullptr || mCreateBuilder == nullptr) {
80         ALOGD("Handle or CreateBuilder symbol is null");
81         return nullptr;
82     }
83     return mCreateBuilder();
84 }
85 
createInputSurface()86 PersistentSurface *StagefrightPluginLoader::createInputSurface() {
87     if (mLibHandle == nullptr || mCreateInputSurface == nullptr) {
88         ALOGD("Handle or CreateInputSurface symbol is null");
89         return nullptr;
90     }
91     return mCreateInputSurface();
92 }
93 
94 //static
GetCCodecInstance()95 const std::unique_ptr<StagefrightPluginLoader> &StagefrightPluginLoader::GetCCodecInstance() {
96     Mutex::Autolock _l(sMutex);
97     if (!sInstance) {
98         ALOGV("Loading library");
99         sInstance.reset(new StagefrightPluginLoader(kCCodecPluginPath));
100     }
101     return sInstance;
102 }
103 
104 }  // namespace android
105