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