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 "plugin_server.h"
17#include "gst_plugin_fw.h"
18#include "image_log.h"
19#include "map"
20#include "new"
21#include "platform_adp.h"
22#include "plugin_common_type.h"
23#include "plugin_errors.h"
24#include "plugin_fw.h"
25#include "singleton.h"
26#include "string"
27#include "type_traits"
28#include "vector"
29
30#undef LOG_DOMAIN
31#define LOG_DOMAIN LOG_TAG_DOMAIN_ID_PLUGIN
32
33#undef LOG_TAG
34#define LOG_TAG "PluginServer"
35
36namespace OHOS {
37namespace MultimediaPlugin {
38using std::map;
39using std::string;
40using std::vector;
41
42uint32_t PluginServer::Register(vector<string> &&pluginPaths)
43{
44    if (pluginPaths.empty()) {
45        return pluginFw_.Register(pluginPaths);
46    }
47    vector<string> canonicalPaths;
48    vector<string> gstCanonicalPaths;
49    for (string &path : pluginPaths) {
50        if (platformAdp_.CheckAndNormalizePath(path) != SUCCESS) {
51            IMAGE_LOGE("failed to check and normalize path: %{public}s.", path.c_str());
52            continue;
53        }
54
55        PluginFWType fwType = AnalyzeFWType(path);
56        switch (fwType) {
57            case PluginFWType::PLUGIN_FW_GENERAL: {
58                // directory path parameters, usually not too much, will not cause massive logs.
59                IMAGE_LOGD("PluginFW path: %{public}s.", path.c_str());
60                canonicalPaths.push_back(std::move(path));
61                break;
62            }
63            case PluginFWType::PLUGIN_FW_GSTREAMER: {
64                // directory path parameters, usually not too much, will not cause massive logs.
65                IMAGE_LOGD("GstPluginFW path: %{public}s.", path.c_str());
66                gstCanonicalPaths.push_back(std::move(path));
67                break;
68            }
69            default: {
70                IMAGE_LOGE("unknown FWType: %{public}d.", fwType);
71            }
72        }
73    }
74
75    if (canonicalPaths.empty() && gstCanonicalPaths.empty()) {
76        IMAGE_LOGE("failed to find any valid plugin path.");
77        return ERR_INVALID_PARAMETER;
78    }
79
80    if (!gstCanonicalPaths.empty()) {
81        uint32_t result = gstPluginFw_.Register(gstCanonicalPaths);
82        if (result != SUCCESS) {
83            IMAGE_LOGE("failed to register gst plugin path, ERRNO: %{public}u.", result);
84            return result;
85        }
86    }
87
88    if (!canonicalPaths.empty()) {
89        uint32_t result = pluginFw_.Register(canonicalPaths);
90        if (result != SUCCESS) {
91            IMAGE_LOGE("failed to register plugin path, ERRNO: %{public}u.", result);
92            return result;
93        }
94    }
95
96    return SUCCESS;
97}
98
99// ------------------------------- private method -------------------------------
100PluginServer::PluginServer()
101    : platformAdp_(DelayedRefSingleton<PlatformAdp>::GetInstance()),
102      pluginFw_(DelayedRefSingleton<PluginFw>::GetInstance()),
103      gstPluginFw_(DelayedRefSingleton<GstPluginFw>::GetInstance()) {}
104
105PluginServer::~PluginServer() {}
106
107PluginClassBase *PluginServer::CreateObject(uint16_t interfaceID, const string &className, uint32_t &errorCode)
108{
109    IMAGE_LOGD("create object iid: %{public}u, className: %{public}s.", interfaceID, className.c_str());
110    PluginClassBase *obj = nullptr;
111    // if it is a pipeline service, use the gstreamer framework first.
112    if (GetInterfaceIDType(interfaceID) == IID_TYPE_PIPELINE) {
113        IMAGE_LOGD("it is a pipeline interface type.");
114        obj = gstPluginFw_.CreateObject(interfaceID, className, errorCode);
115        if (obj != nullptr) {
116            return obj;
117        }
118    }
119
120    obj = pluginFw_.CreateObject(interfaceID, className, errorCode);
121    return obj;
122}
123
124PluginClassBase *PluginServer::CreateObject(uint16_t interfaceID, uint16_t serviceType,
125                                            const map<string, AttrData> &capabilities,
126                                            const PriorityScheme &priorityScheme, uint32_t &errorCode)
127{
128    IMAGE_LOGD("create object iid: %{public}hu, service Type: %{public}u.", interfaceID, serviceType);
129    PluginClassBase *obj = nullptr;
130    // if it is a pipeline service, use the gstreamer framework first.
131    if (GetInterfaceIDType(interfaceID) == IID_TYPE_PIPELINE) {
132        IMAGE_LOGD("it is a pipeline interface type.");
133        obj = gstPluginFw_.CreateObject(interfaceID, serviceType, capabilities, priorityScheme, errorCode);
134        if (obj != nullptr) {
135            return obj;
136        }
137    }
138
139    obj = pluginFw_.CreateObject(interfaceID, serviceType, capabilities, priorityScheme, errorCode);
140    return obj;
141}
142
143uint32_t PluginServer::PluginServerGetClassInfo(uint16_t interfaceID, uint16_t serviceType,
144                                                const map<std::string, AttrData> &capabilities,
145                                                vector<ClassInfo> &classesInfo)
146{
147    if (!classesInfo.empty()) {
148        classesInfo.clear();
149    }
150
151    uint32_t resultGst = ERR_MATCHING_PLUGIN;
152    // if it is a pipeline service, use the gstreamer framework first.
153    if (GetInterfaceIDType(interfaceID) == IID_TYPE_PIPELINE) {
154        resultGst = gstPluginFw_.GstPluginFwGetClassInfo(interfaceID, serviceType, capabilities, classesInfo);
155    }
156
157    // if the previous process has added classesInfo, the effect here is to append some other classesInfo.
158    uint32_t resultFw = pluginFw_.PluginFwGetClassInfo(interfaceID, serviceType, capabilities, classesInfo);
159
160    // if both gstreamer and self-developing plugin can not get class information, then considered fail.
161    if ((resultGst != SUCCESS) && (resultFw != SUCCESS)) {
162        IMAGE_LOGE("failed to get class by serviceType, resultGst: %{public}u, resultFw: %{public}u.",
163            resultGst, resultFw);
164        return resultFw;
165    }
166
167    return SUCCESS;
168}
169
170PluginFWType PluginServer::AnalyzeFWType(const string &canonicalPath)
171{
172    // for the current rule, contains the word "/gstreamer" is considered to be the gstreamer plugin directory.
173    if (canonicalPath.find(platformAdp_.DIR_SEPARATOR + "gstreamer") != string::npos) {
174        return PluginFWType::PLUGIN_FW_GSTREAMER;
175    }
176
177    return PluginFWType::PLUGIN_FW_GENERAL;
178}
179} // namespace MultimediaPlugin
180} // namespace OHOS
181