1 /*
2 * Copyright (C) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "engine_factory_repo.h"
17 #include <limits>
18 #include <cinttypes>
19 #include <dlfcn.h>
20 #include "directory_ex.h"
21 #include "media_errors.h"
22 #include "media_log.h"
23 #include "parameter.h"
24
25 namespace {
26 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "EngineFactoryRepo"};
27 #ifdef __aarch64__
28 static const std::string MEDIA_ENGINE_LIB_PATH = "/system/lib64/media";
29 #else
30 static const std::string MEDIA_ENGINE_LIB_PATH = "/system/lib/media";
31 #endif
32 static const std::string MEDIA_ENGINE_LIB_NAME_GSTREAMER = "libmedia_engine_gst.z.so";
33 static const std::string MEDIA_ENGINE_LIB_NAME_HISTREAMER = "libmedia_engine_histreamer.z.so";
34 static const std::string MEDIA_ENGINE_ENTRY_SYMBOL = "CreateEngineFactory";
35 }
36
37 namespace OHOS {
38 namespace Media {
39 using CreateFactoryFunc = IEngineFactory *(*)();
40
Instance()41 EngineFactoryRepo &EngineFactoryRepo::Instance()
42 {
43 static EngineFactoryRepo inst;
44 return inst;
45 }
46
~EngineFactoryRepo()47 EngineFactoryRepo::~EngineFactoryRepo()
48 {
49 for (auto &lib : factoryLibs_) {
50 if (lib != nullptr) {
51 (void)dlclose(lib);
52 lib = nullptr;
53 }
54 }
55 }
56
LoadLib(const std::string & libPath)57 void EngineFactoryRepo::LoadLib(const std::string &libPath)
58 {
59 void *handle = dlopen(libPath.c_str(), RTLD_NOW | RTLD_LOCAL);
60 if (handle == nullptr) {
61 MEDIA_LOGE("failed to dlopen %{public}s, errno:%{public}d, errormsg:%{public}s",
62 libPath.c_str(), errno, dlerror());
63 return;
64 }
65
66 CreateFactoryFunc entry = reinterpret_cast<CreateFactoryFunc>(dlsym(handle, MEDIA_ENGINE_ENTRY_SYMBOL.c_str()));
67 if (entry == nullptr) {
68 MEDIA_LOGE("failed to dlsym %{public}s for lib %{public}s, errno:%{public}d, errormsg:%{public}s",
69 MEDIA_ENGINE_ENTRY_SYMBOL.c_str(), libPath.c_str(), errno, dlerror());
70 (void)dlclose(handle);
71 return;
72 }
73
74 std::shared_ptr<IEngineFactory> factory = std::shared_ptr<IEngineFactory>(entry());
75 if (factory == nullptr) {
76 MEDIA_LOGE("failed to create engine factory for lib: %{public}s", libPath.c_str());
77 (void)dlclose(handle);
78 return;
79 }
80
81 factoryLibs_.push_back(handle);
82 factorys_.push_back(factory);
83 }
84
LoadGstreamerEngine()85 int32_t EngineFactoryRepo::LoadGstreamerEngine()
86 {
87 std::unique_lock<std::mutex> lock(mutex_);
88 if (gstreamerLoad_) {
89 return MSERR_OK;
90 }
91
92 std::vector<std::string> allFiles;
93 GetDirFiles(MEDIA_ENGINE_LIB_PATH, allFiles);
94 for (auto &file : allFiles) {
95 std::string::size_type namePos = file.find(MEDIA_ENGINE_LIB_NAME_GSTREAMER);
96 if (namePos == std::string::npos) {
97 continue;
98 } else {
99 LoadLib(file);
100 gstreamerLoad_ = true;
101 break;
102 }
103 }
104 return MSERR_OK;
105 }
106
LoadHistreamerEngine()107 int32_t EngineFactoryRepo::LoadHistreamerEngine()
108 {
109 std::unique_lock<std::mutex> lock(mutex_);
110 if (histreamerLoad_) {
111 MEDIA_LOGI("histramer is enabled");
112 return MSERR_OK;
113 }
114
115 char useHistreamer[10] = {0}; // 10 for system parameter usage
116 auto res = GetParameter("debug.media_service.histreamer", "0", useHistreamer, sizeof(useHistreamer));
117 if (res == 1 && useHistreamer[0] == '1') {
118 std::vector<std::string> allFiles;
119 GetDirFiles(MEDIA_ENGINE_LIB_PATH, allFiles);
120 for (auto &file : allFiles) {
121 std::string::size_type namePos = file.find(MEDIA_ENGINE_LIB_NAME_HISTREAMER);
122 if (namePos == std::string::npos) {
123 continue;
124 } else {
125 LoadLib(file);
126 histreamerLoad_ = true;
127 break;
128 }
129 }
130 }
131
132 return MSERR_OK;
133 }
134
GetEngineFactory(IEngineFactory::Scene scene,const std::string & uri)135 std::shared_ptr<IEngineFactory> EngineFactoryRepo::GetEngineFactory(
136 IEngineFactory::Scene scene, const std::string &uri)
137 {
138 (void)LoadGstreamerEngine();
139 (void)LoadHistreamerEngine();
140
141 int32_t maxScore = std::numeric_limits<int32_t>::min();
142 std::shared_ptr<IEngineFactory> target = nullptr;
143 for (auto &factory : factorys_) {
144 int32_t score = factory->Score(scene, uri);
145 if (maxScore < score) {
146 maxScore = score;
147 target = factory;
148 }
149 }
150 if (target == nullptr && !factorys_.empty()) {
151 target = factorys_.front();
152 }
153
154 MEDIA_LOGI("Selected factory: 0x%{public}06" PRIXPTR ", score: %{public}d", FAKE_POINTER(target.get()), maxScore);
155 return target;
156 }
157 } // namespace Media
158 } // namespace OHOS
159