1 /*
2 * Copyright (c) 2023-2023 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 #define HST_LOG_TAG "FilterBase"
17
18 #include "pipeline/core/filter_base.h"
19 #include <algorithm>
20 #include "foundation/log.h"
21 #include "pipeline/filters/common/plugin_settings.h"
22 #include "pipeline/filters/common/plugin_utils.h"
23 #include "plugin/common/plugin_attr_desc.h"
24
25 namespace OHOS {
26 namespace Media {
27 namespace Pipeline {
FilterBase(std::string name)28 FilterBase::FilterBase(std::string name)
29 : name_(std::move(name)), state_(FilterState::CREATED), eventReceiver_(nullptr), callback_(nullptr)
30 {
31 inPorts_.reserve(MAX_PORT_NUMBER);
32 outPorts_.reserve(MAX_PORT_NUMBER);
33 routeMap_.reserve(MAX_ROUTE_NUMBER);
34 }
35
Init(EventReceiver * receiver,FilterCallback * callback)36 void FilterBase::Init(EventReceiver* receiver, FilterCallback* callback)
37 {
38 this->eventReceiver_ = receiver;
39 this->callback_ = callback;
40 InitPorts();
41 state_ = FilterState::INITIALIZED;
42 }
43
GetInPort(const std::string & name)44 std::shared_ptr<InPort> FilterBase::GetInPort(const std::string& name)
45 {
46 auto port = FindPort(inPorts_, name);
47 FALSE_RETURN_V(port != nullptr, EmptyInPort::GetInstance());
48 return port;
49 }
50
GetOutPort(const std::string & name)51 std::shared_ptr<OutPort> FilterBase::GetOutPort(const std::string& name)
52 {
53 auto port = FindPort(outPorts_, name);
54 FALSE_RETURN_V(port != nullptr, EmptyOutPort::GetInstance());
55 return port;
56 }
57
Prepare()58 ErrorCode FilterBase::Prepare()
59 {
60 MEDIA_LOG_I("prepare is called");
61 FALSE_RETURN_V_MSG_W(state_ == FilterState::INITIALIZED, ErrorCode::ERROR_INVALID_OPERATION,
62 "filter is not in init state");
63 state_ = FilterState::PREPARING;
64
65 // Filter默认InPort按Push方式获取数据
66 // 只有 Demuxer 的 Prepare() 需要覆写此实现, Demuxer的 InPort可能按 Pull 或 Push 方式获取数据
67 WorkMode mode;
68 return GetInPort(PORT_NAME_DEFAULT)->Activate({WorkMode::PUSH}, mode);
69 }
70
Start()71 ErrorCode FilterBase::Start()
72 {
73 MEDIA_LOG_I("start called");
74 state_ = FilterState::RUNNING;
75 return ErrorCode::SUCCESS;
76 }
77
Pause()78 ErrorCode FilterBase::Pause()
79 {
80 MEDIA_LOG_I("pause called");
81 state_ = FilterState::PAUSED;
82 return ErrorCode::SUCCESS;
83 }
84
Stop()85 ErrorCode FilterBase::Stop()
86 {
87 state_ = FilterState::INITIALIZED;
88 mediaTypeCntMap_.clear();
89 return ErrorCode::SUCCESS;
90 }
91
UnlinkPrevFilters()92 void FilterBase::UnlinkPrevFilters()
93 {
94 for (auto&& inPort : inPorts_) {
95 auto peer = inPort->GetPeerPort();
96 inPort->Disconnect();
97 if (peer) {
98 peer->Disconnect();
99 }
100 }
101 }
102
GetNextFilters()103 std::vector<Filter*> FilterBase::GetNextFilters()
104 {
105 std::vector<Filter*> nextFilters;
106 nextFilters.reserve(outPorts_.size());
107 for (auto&& outPort : outPorts_) {
108 auto peerPort = outPort->GetPeerPort();
109 if (!peerPort) {
110 MEDIA_LOG_I("Filter " PUBLIC_LOG_S " outport " PUBLIC_LOG_S " has no peer port (" PUBLIC_LOG_ZU
111 ").", name_.c_str(), outPort->GetName().c_str(), outPorts_.size());
112 continue;
113 }
114 auto filter = const_cast<Filter*>(reinterpret_cast<const Filter*>(peerPort->GetOwnerFilter()));
115 if (filter) {
116 nextFilters.emplace_back(filter);
117 }
118 }
119 return nextFilters;
120 }
121
GetPreFilters()122 std::vector<Filter*> FilterBase::GetPreFilters()
123 {
124 std::vector<Filter*> preFilters;
125 preFilters.reserve(inPorts_.size());
126 for (auto&& inPort : inPorts_) {
127 auto peerPort = inPort->GetPeerPort();
128 if (!peerPort) {
129 MEDIA_LOG_I("Filter " PUBLIC_LOG_S " inport " PUBLIC_LOG_S " has no peer port (" PUBLIC_LOG_ZU
130 ").", name_.c_str(), inPort->GetName().c_str(), inPorts_.size());
131 continue;
132 }
133 auto filter = const_cast<Filter*>(reinterpret_cast<const Filter*>(peerPort->GetOwnerFilter()));
134 if (filter) {
135 preFilters.emplace_back(filter);
136 }
137 }
138 return preFilters;
139 }
140
PushData(const std::string & inPort,const AVBufferPtr & buffer,int64_t offset)141 ErrorCode FilterBase::PushData(const std::string& inPort, const AVBufferPtr& buffer, int64_t offset)
142 {
143 UNUSED_VARIABLE(inPort);
144 UNUSED_VARIABLE(buffer);
145 UNUSED_VARIABLE(offset);
146 return ErrorCode::SUCCESS;
147 }
148
PullData(const std::string & outPort,uint64_t offset,size_t size,AVBufferPtr & data)149 ErrorCode FilterBase::PullData(const std::string& outPort, uint64_t offset, size_t size, AVBufferPtr& data)
150 {
151 UNUSED_VARIABLE(outPort);
152 UNUSED_VARIABLE(offset);
153 UNUSED_VARIABLE(size);
154 UNUSED_VARIABLE(data);
155 return ErrorCode::SUCCESS;
156 }
157
OnEvent(const Event & event)158 void FilterBase::OnEvent(const Event& event)
159 {
160 // Receive event from port, pass it to pipeline
161 if (eventReceiver_) {
162 eventReceiver_->OnEvent(event);
163 }
164 }
165
InitPorts()166 void FilterBase::InitPorts()
167 {
168 inPorts_.clear();
169 outPorts_.clear();
170
171 auto inPort = std::make_shared<InPort>(this);
172 inPorts_.push_back(inPort);
173
174 auto outPort = std::make_shared<OutPort>(this);
175 outPorts_.push_back(outPort);
176 routeMap_.emplace_back(inPort->GetName(), outPort->GetName());
177 }
178
179 template <typename T>
FindPort(const std::vector<T> & list,const std::string & name)180 T FilterBase::FindPort(const std::vector<T>& list, const std::string& name)
181 {
182 auto find = std::find_if(list.begin(), list.end(), [name](const T& item) {
183 if (item == nullptr) {
184 return false;
185 }
186 return name == item->GetName();
187 });
188 if (find != list.end()) {
189 return *find;
190 }
191 MEDIA_LOG_E("Find port(" PUBLIC_LOG_S ") failed.", name.c_str());
192 return nullptr;
193 }
194
ConfigPluginWithMeta(Plugin::Base & plugin,const Plugin::Meta & meta)195 ErrorCode FilterBase::ConfigPluginWithMeta(Plugin::Base& plugin, const Plugin::Meta& meta)
196 {
197 auto parameterMap = PluginParameterTable::GetInstance().FindAllowedParameterMap(filterType_);
198 for (const auto& keyPair : parameterMap) {
199 if ((keyPair.second.second & PARAM_SET) == 0) {
200 continue;
201 }
202 Plugin::ValueType outValPtr;
203 auto ret = meta.GetData(static_cast<Plugin::Tag>(keyPair.first), outValPtr);
204 if (ret && keyPair.second.first(keyPair.first, outValPtr)) {
205 if (plugin.SetParameter(keyPair.first, outValPtr) != Plugin::Status::OK) {
206 MEDIA_LOG_W("set parameter " PUBLIC_LOG_S "(" PUBLIC_LOG_D32 ") on plugin " PUBLIC_LOG_S " failed",
207 Plugin::GetTagStrName(keyPair.first), keyPair.first, plugin.GetName().c_str());
208 }
209 } else {
210 if (!Plugin::HasTagInfo(keyPair.first)) {
211 MEDIA_LOG_W("tag " PUBLIC_LOG_D32 " is not in map, may be update it?", keyPair.first);
212 } else {
213 MEDIA_LOG_W("parameter " PUBLIC_LOG_S " in meta is not found or type mismatch",
214 Plugin::GetTagStrName(keyPair.first));
215 }
216 }
217 }
218 return ErrorCode::SUCCESS;
219 }
220
NamePort(const std::string & mime)221 std::string FilterBase::NamePort(const std::string& mime)
222 {
223 auto type = mime.substr(0, mime.find_first_of('/'));
224 if (type.empty()) {
225 type = "default";
226 }
227 auto cnt = ++(mediaTypeCntMap_[name_ + type]);
228 auto portName = type + "_" + std::to_string(cnt);
229 return portName;
230 }
231
GetRouteInPort(const std::string & outPortName)232 PInPort FilterBase::GetRouteInPort(const std::string& outPortName)
233 {
234 auto ite = std::find_if(routeMap_.begin(), routeMap_.end(),
235 [&outPortName](const PairPort& pp) { return outPortName == pp.second; });
236 if (ite == routeMap_.end()) {
237 MEDIA_LOG_W("out port " PUBLIC_LOG_S " has no route map port", outPortName.c_str());
238 return nullptr;
239 }
240 return GetInPort(ite->first);
241 }
242
GetRouteOutPort(const std::string & inPortName)243 POutPort FilterBase::GetRouteOutPort(const std::string& inPortName)
244 {
245 auto ite = std::find_if(routeMap_.begin(), routeMap_.end(),
246 [&inPortName](const PairPort& pp) { return inPortName == pp.first; });
247 if (ite == routeMap_.end()) {
248 MEDIA_LOG_W("in port " PUBLIC_LOG_S " has no route map port", inPortName.c_str());
249 return nullptr;
250 }
251 return GetOutPort(ite->second);
252 }
253
254 template <typename T>
UpdateAndInitPluginByInfo(std::shared_ptr<T> & plugin,std::shared_ptr<Plugin::PluginInfo> & pluginInfo,const std::shared_ptr<Plugin::PluginInfo> & selectedPluginInfo,const std::function<std::shared_ptr<T> (const std::string &)> & pluginCreator)255 bool FilterBase::UpdateAndInitPluginByInfo(std::shared_ptr<T>& plugin, std::shared_ptr<Plugin::PluginInfo>& pluginInfo,
256 const std::shared_ptr<Plugin::PluginInfo>& selectedPluginInfo,
257 const std::function<std::shared_ptr<T>(const std::string&)>& pluginCreator)
258 {
259 if (selectedPluginInfo == nullptr) {
260 MEDIA_LOG_W("no available info to update plugin");
261 return false;
262 }
263 if (plugin != nullptr) {
264 if (pluginInfo != nullptr && pluginInfo->name == selectedPluginInfo->name) {
265 if (plugin->Reset() == Plugin::Status::OK) {
266 return true;
267 }
268 MEDIA_LOG_W("reuse previous plugin " PUBLIC_LOG_S " failed, will create new plugin",
269 pluginInfo->name.c_str());
270 }
271 plugin->Deinit();
272 }
273
274 plugin = pluginCreator(selectedPluginInfo->name);
275 if (plugin == nullptr) {
276 MEDIA_LOG_E("cannot create plugin " PUBLIC_LOG_S, selectedPluginInfo->name.c_str());
277 return false;
278 }
279 auto err = TranslatePluginStatus(plugin->Init());
280 if (err != ErrorCode::SUCCESS) {
281 MEDIA_LOG_E("plugin " PUBLIC_LOG_S " init error", selectedPluginInfo->name.c_str());
282 return false;
283 }
284 pluginInfo = selectedPluginInfo;
285 return true;
286 }
287 template bool FilterBase::UpdateAndInitPluginByInfo(std::shared_ptr<Plugin::Codec>& plugin,
288 std::shared_ptr<Plugin::PluginInfo>& pluginInfo,
289 const std::shared_ptr<Plugin::PluginInfo>& selectedPluginInfo,
290 const std::function<std::shared_ptr<Plugin::Codec>(const std::string&)>& pluginCreator);
291 template bool FilterBase::UpdateAndInitPluginByInfo(std::shared_ptr<Plugin::AudioSink>& plugin,
292 std::shared_ptr<Plugin::PluginInfo>& pluginInfo,
293 const std::shared_ptr<Plugin::PluginInfo>& selectedPluginInfo,
294 const std::function<std::shared_ptr<Plugin::AudioSink>(const std::string&)>& pluginCreator);
295 template bool FilterBase::UpdateAndInitPluginByInfo(std::shared_ptr<Plugin::VideoSink>& plugin,
296 std::shared_ptr<Plugin::PluginInfo>& pluginInfo,
297 const std::shared_ptr<Plugin::PluginInfo>& selectedPluginInfo,
298 const std::function<std::shared_ptr<Plugin::VideoSink>(const std::string&)>& pluginCreator);
299 template bool FilterBase::UpdateAndInitPluginByInfo(std::shared_ptr<Plugin::OutputSink>& plugin,
300 std::shared_ptr<Plugin::PluginInfo>& pluginInfo,
301 const std::shared_ptr<Plugin::PluginInfo>& selectedPluginInfo,
302 const std::function<std::shared_ptr<Plugin::OutputSink>(const std::string&)>& pluginCreator);
303
OnEvent(const Plugin::PluginEvent & event)304 void FilterBase::OnEvent(const Plugin::PluginEvent &event)
305 {
306 if (eventReceiver_ != nullptr) {
307 if (event.type == Plugin::PluginEventType::CLIENT_ERROR ||
308 event.type == Plugin::PluginEventType::SERVER_ERROR ||
309 event.type == Plugin::PluginEventType::OTHER_ERROR) {
310 eventReceiver_->OnEvent({name_, EventType::EVENT_PLUGIN_ERROR, event});
311 } else {
312 eventReceiver_->OnEvent({name_, EventType::EVENT_PLUGIN_EVENT, event});
313 }
314 }
315 }
316
SetSyncCenter(std::weak_ptr<IMediaSyncCenter> syncCenter)317 void FilterBase::SetSyncCenter(std::weak_ptr<IMediaSyncCenter> syncCenter)
318 {
319 syncCenter_ = syncCenter;
320 }
321 } // namespace Pipeline
322 } // namespace Media
323 } // namespace OHOS
324