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