• 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 #if defined(RECORDER_SUPPORT) && defined(VIDEO_SUPPORT)
17 
18 #define HST_LOG_TAG "VideoCaptureFilter"
19 
20 #include "pipeline/filters/source/video_capture/video_capture_filter.h"
21 #include "foundation/log.h"
22 #include "pipeline/factory/filter_factory.h"
23 #include "pipeline/filters/common/plugin_utils.h"
24 #include "plugin/common/plugin_attr_desc.h"
25 
26 namespace OHOS {
27 namespace Media {
28 namespace Pipeline {
29 using namespace Plugin;
30 
31 static AutoRegisterFilter<VideoCaptureFilter> g_registerFilterHelper("builtin.recorder.videocapture");
32 
VideoCaptureFilter(const std::string & name)33 VideoCaptureFilter::VideoCaptureFilter(const std::string& name)
34     : FilterBase(name),
35       taskPtr_(nullptr),
36       plugin_(nullptr),
37       pluginAllocator_(nullptr),
38       pluginInfo_(nullptr)
39 {
40     filterType_ = FilterType::CAPTURE_SOURCE;
41     MEDIA_LOG_D("ctor called");
42 }
43 
~VideoCaptureFilter()44 VideoCaptureFilter::~VideoCaptureFilter()
45 {
46     MEDIA_LOG_D("dtor called");
47     if (taskPtr_) {
48         taskPtr_->Stop();
49     }
50     if (plugin_) {
51         plugin_->Deinit();
52     }
53 }
54 
GetWorkModes()55 std::vector<WorkMode> VideoCaptureFilter::GetWorkModes()
56 {
57     return {WorkMode::PUSH};
58 }
59 
InitAndConfigPlugin(const std::shared_ptr<Plugin::Meta> & videoMeta)60 ErrorCode VideoCaptureFilter::InitAndConfigPlugin(const std::shared_ptr<Plugin::Meta>& videoMeta)
61 {
62     MEDIA_LOG_D("IN");
63     ErrorCode err = TranslatePluginStatus(plugin_->Init());
64     if (err != ErrorCode::SUCCESS) {
65         return err;
66     }
67     plugin_->SetCallback(this);
68     pluginAllocator_ = plugin_->GetAllocator();
69     err = TranslatePluginStatus(plugin_->SetParameter(Tag::VIDEO_WIDTH, videoWidth_));
70     if (err != ErrorCode::SUCCESS) {
71         return err;
72     }
73     err = TranslatePluginStatus(plugin_->SetParameter(Tag::VIDEO_HEIGHT, videoHeight_));
74     if (err != ErrorCode::SUCCESS) {
75         return err;
76     }
77     err = TranslatePluginStatus(plugin_->SetParameter(Tag::VIDEO_CAPTURE_RATE, captureRate_));
78     if (err != ErrorCode::SUCCESS) {
79         return err;
80     }
81     err = TranslatePluginStatus(plugin_->SetParameter(Tag::VIDEO_PIXEL_FORMAT, pixelFormat_));
82     if (err != ErrorCode::SUCCESS) {
83         return err;
84     }
85     return ErrorCode::SUCCESS;
86 }
87 
SetParameter(int32_t key,const Plugin::Any & value)88 ErrorCode VideoCaptureFilter::SetParameter(int32_t key, const Plugin::Any& value)
89 {
90     auto tag = static_cast<OHOS::Media::Plugin::Tag>(key);
91     switch (tag) {
92         case Tag::SRC_INPUT_TYPE:
93             inputTypeSpecified_ = AssignParameterIfMatch(tag, inputType_, value);
94             if (inputType_ == Plugin::SrcInputType::VID_SURFACE_YUV) {
95                 pixelFormat_ = Plugin::VideoPixelFormat::YUV420P;
96             } else if (inputType_ == Plugin::SrcInputType::VID_SURFACE_RGB) {
97                 pixelFormat_ = Plugin::VideoPixelFormat::RGBA;
98             } else {
99                 MEDIA_LOG_W("unsupport inputType: " PUBLIC_LOG_U32, inputType_);
100             }
101             break;
102         case Tag::VIDEO_WIDTH:
103             (void)AssignParameterIfMatch(tag, videoWidth_, value);
104             break;
105         case Tag::VIDEO_HEIGHT:
106             (void)AssignParameterIfMatch(tag, videoHeight_, value);
107             break;
108         case Tag::VIDEO_CAPTURE_RATE:
109             (void)AssignParameterIfMatch(tag, captureRate_, value);
110             break;
111         case Tag::MEDIA_BITRATE:
112             (void)AssignParameterIfMatch(tag, bitRate_, value);
113             break;
114         case Tag::VIDEO_FRAME_RATE:
115             (void)AssignParameterIfMatch(tag, frameRate_, value);
116             break;
117         default:
118             MEDIA_LOG_W("Unknown key " PUBLIC_LOG_S, Plugin::GetTagStrName(tag));
119             break;
120     }
121     return ErrorCode::SUCCESS;
122 }
123 
GetParameter(int32_t key,Plugin::Any & value)124 ErrorCode VideoCaptureFilter::GetParameter(int32_t key, Plugin::Any& value)
125 {
126     Tag tag = static_cast<Plugin::Tag>(key);
127     switch (tag) {
128         case Tag::SRC_INPUT_TYPE: {
129             value = inputType_;
130             break;
131         }
132         case Tag::VIDEO_WIDTH: {
133             value = videoWidth_;
134             break;
135         }
136         case Tag::VIDEO_HEIGHT: {
137             value = videoHeight_;
138             break;
139         }
140         case Tag::VIDEO_CAPTURE_RATE: {
141             value = captureRate_;
142             break;
143         }
144         case Tag::VIDEO_SURFACE: {
145             if (plugin_ != nullptr) {
146                 plugin_->GetParameter(tag, value);
147             }
148             break;
149         }
150         default:
151             MEDIA_LOG_W("Unknown key " PUBLIC_LOG_S, Plugin::GetTagStrName(tag));
152             break;
153     }
154     return ErrorCode::SUCCESS;
155 }
156 
DoConfigure()157 ErrorCode VideoCaptureFilter::DoConfigure()
158 {
159     auto emptyMeta = std::make_shared<Plugin::Meta>();
160     auto videoMeta = std::make_shared<Plugin::Meta>();
161     if (!MergeMetaWithCapability(*emptyMeta, capNegWithDownstream_, *videoMeta)) {
162         MEDIA_LOG_E("cannot find available capability of plugin " PUBLIC_LOG_S, pluginInfo_->name.c_str());
163         return ErrorCode::ERROR_UNKNOWN;
164     }
165     FALSE_LOG(videoMeta->Set<Plugin::Tag::VIDEO_WIDTH>(videoWidth_));
166     FALSE_LOG(videoMeta->Set<Plugin::Tag::VIDEO_HEIGHT>(videoHeight_));
167     FALSE_LOG(videoMeta->Set<Plugin::Tag::MEDIA_BITRATE>(bitRate_));
168     FALSE_LOG(videoMeta->Set<Plugin::Tag::VIDEO_FRAME_RATE>(frameRate_));
169     FALSE_LOG(videoMeta->Set<Plugin::Tag::MIME>(mime_));
170     FALSE_LOG(videoMeta->Set<Plugin::Tag::VIDEO_PIXEL_FORMAT>(pixelFormat_));
171     Plugin::Meta upstreamParams;
172     Plugin::Meta downstreamParams;
173     if (!outPorts_[0]->Configure(videoMeta, upstreamParams, downstreamParams)) {
174         MEDIA_LOG_E("Configure downstream fail");
175         return ErrorCode::ERROR_UNKNOWN;
176     }
177     return InitAndConfigPlugin(videoMeta);
178 }
179 
Prepare()180 ErrorCode VideoCaptureFilter::Prepare()
181 {
182     MEDIA_LOG_I("Prepare entered.");
183     if (!taskPtr_) {
184         taskPtr_ = std::make_shared<OSAL::Task>("DataReader");
185         taskPtr_->RegisterHandler([this] { ReadLoop(); });
186     }
187     ErrorCode err = FindPlugin();
188     if (err != ErrorCode::SUCCESS || !plugin_) {
189         MEDIA_LOG_E("Find plugin fail");
190         return err;
191     }
192     err = DoConfigure();
193     if (err != ErrorCode::SUCCESS) {
194         MEDIA_LOG_E("DoConfigure fail");
195         return err;
196     }
197     err = TranslatePluginStatus(plugin_->Prepare());
198     if (err == ErrorCode::SUCCESS) {
199         MEDIA_LOG_D("media source send EVENT_READY");
200         OnEvent(Event{name_, EventType::EVENT_READY, {}});
201     }
202     return err;
203 }
204 
Start()205 ErrorCode VideoCaptureFilter::Start()
206 {
207     MEDIA_LOG_I("Start entered.");
208     if (taskPtr_) {
209         taskPtr_->Start();
210     }
211     return plugin_ ? TranslatePluginStatus(plugin_->Start()) : ErrorCode::ERROR_INVALID_OPERATION;
212 }
213 
Stop()214 ErrorCode VideoCaptureFilter::Stop()
215 {
216     MEDIA_LOG_I("Stop entered.");
217     if (taskPtr_) {
218         taskPtr_->Stop();
219     }
220     ErrorCode ret = ErrorCode::SUCCESS;
221     if (plugin_) {
222         ret = TranslatePluginStatus(plugin_->Stop());
223     }
224     return ret;
225 }
226 
Pause()227 ErrorCode VideoCaptureFilter::Pause()
228 {
229     MEDIA_LOG_I("Pause entered.");
230     if (taskPtr_) {
231         taskPtr_->PauseAsync();
232     }
233     ErrorCode ret = ErrorCode::SUCCESS;
234     if (plugin_) {
235         ret = TranslatePluginStatus(plugin_->Stop());
236     }
237     return ret;
238 }
239 
Resume()240 ErrorCode VideoCaptureFilter::Resume()
241 {
242     MEDIA_LOG_I("Resume entered.");
243     if (taskPtr_) {
244         taskPtr_->Start();
245     }
246     return plugin_ ? TranslatePluginStatus(plugin_->Start()) : ErrorCode::ERROR_INVALID_OPERATION;
247 }
248 
SendEos()249 ErrorCode VideoCaptureFilter::SendEos()
250 {
251     MEDIA_LOG_I("SendEos entered.");
252     Stop();
253     auto eosBuffer = std::make_shared<AVBuffer>();
254     eosBuffer->flag |= BUFFER_FLAG_EOS;
255     SendBuffer(eosBuffer);
256     isEos_ = true;
257     return ErrorCode::SUCCESS;
258 }
259 
InitPorts()260 void VideoCaptureFilter::InitPorts()
261 {
262     MEDIA_LOG_D("IN");
263     auto outPort = std::make_shared<OutPort>(this);
264     outPorts_.push_back(outPort);
265 }
266 
ReadLoop()267 void VideoCaptureFilter::ReadLoop()
268 {
269     if (isEos_.load()) {
270         return;
271     }
272     uint64_t bufferSize = 0;
273     auto ret = plugin_->GetSize(bufferSize);
274     if (ret != Status::OK || bufferSize <= 0) {
275         MEDIA_LOG_E("Get plugin buffer size fail");
276         return;
277     }
278     AVBufferPtr bufferPtr = std::make_shared<AVBuffer>(BufferMetaType::VIDEO);
279     ret = plugin_->Read(bufferPtr, static_cast<size_t>(bufferSize));
280     if (ret != Status::OK) {
281         MEDIA_LOG_D("Read buffer from plugin fail: " PUBLIC_LOG_U32, ret);
282         return;
283     }
284     SendBuffer(bufferPtr);
285     OSAL::SleepFor(10); // 10: sleep 10ms when read one frame
286 }
287 
CreatePlugin(const std::shared_ptr<PluginInfo> & info,const std::string & name,PluginManager & manager)288 ErrorCode VideoCaptureFilter::CreatePlugin(const std::shared_ptr<PluginInfo>& info, const std::string& name,
289                                            PluginManager& manager)
290 {
291     if ((plugin_ != nullptr) && (pluginInfo_ != nullptr)) {
292         if (info->name == pluginInfo_->name && TranslatePluginStatus(plugin_->Reset()) == ErrorCode::SUCCESS) {
293             MEDIA_LOG_I("Reuse last plugin: " PUBLIC_LOG_S, name.c_str());
294             return ErrorCode::SUCCESS;
295         }
296         if (TranslatePluginStatus(plugin_->Deinit()) != ErrorCode::SUCCESS) {
297             MEDIA_LOG_E("Deinit last plugin: " PUBLIC_LOG_S " error", pluginInfo_->name.c_str());
298         }
299     }
300     plugin_ = manager.CreateSourcePlugin(name);
301     if (plugin_ == nullptr) {
302         MEDIA_LOG_E("PluginManager CreatePlugin " PUBLIC_LOG_S " fail", name.c_str());
303         return ErrorCode::ERROR_UNKNOWN;
304     }
305     pluginInfo_ = info;
306     MEDIA_LOG_I("Create new plugin: " PUBLIC_LOG_S " success", pluginInfo_->name.c_str());
307     return ErrorCode::SUCCESS;
308 }
309 
DoNegotiate(const CapabilitySet & outCaps)310 bool VideoCaptureFilter::DoNegotiate(const CapabilitySet &outCaps)
311 {
312     if (outCaps.empty()) {
313         MEDIA_LOG_E("audio capture plugin must have out caps");
314         return false;
315     }
316     for (const auto& outCap : outCaps) {
317         auto thisOut = std::make_shared<Plugin::Capability>();
318         mime_ = outCap.mime;
319         *thisOut = outCap; // pixel format
320         Plugin::Meta upstreamParams;
321         Plugin::Meta downstreamParams;
322         if (outPorts_[0]->Negotiate(thisOut, capNegWithDownstream_, upstreamParams, downstreamParams)) {
323             MEDIA_LOG_I("Negotiate success");
324             return true;
325         }
326     }
327     return false;
328 }
329 
FindPlugin()330 ErrorCode VideoCaptureFilter::FindPlugin()
331 {
332     if (!inputTypeSpecified_) {
333         MEDIA_LOG_E("Must set input type first");
334         return ErrorCode::ERROR_INVALID_OPERATION;
335     }
336     PluginManager& pluginManager = PluginManager::Instance();
337     auto nameList = pluginManager.ListPlugins(PluginType::SOURCE);
338     for (const std::string& name : nameList) {
339         std::shared_ptr<PluginInfo> info = pluginManager.GetPluginInfo(PluginType::SOURCE, name);
340         MEDIA_LOG_I("name: " PUBLIC_LOG_S ", info->name: " PUBLIC_LOG_S, name.c_str(), info->name.c_str());
341         auto val = info->extra[PLUGIN_INFO_EXTRA_INPUT_TYPE];
342         if (val.SameTypeWith(typeid(Plugin::SrcInputType))) {
343             auto supportInputType = OHOS::Media::Plugin::AnyCast<Plugin::SrcInputType>(val);
344             if (inputType_ == supportInputType && DoNegotiate(info->outCaps) &&
345                 CreatePlugin(info, name, pluginManager) == ErrorCode::SUCCESS) {
346                 MEDIA_LOG_I("CreatePlugin " PUBLIC_LOG_S " success", name_.c_str());
347                 return ErrorCode::SUCCESS;
348             }
349         }
350     }
351     MEDIA_LOG_I("Cannot find any plugin");
352     return ErrorCode::ERROR_UNSUPPORTED_FORMAT;
353 }
354 
SendBuffer(const std::shared_ptr<AVBuffer> & buffer)355 void VideoCaptureFilter::SendBuffer(const std::shared_ptr<AVBuffer>& buffer)
356 {
357     OSAL::ScopedLock lock(pushMutex_);
358     if (!isEos_.load()) {
359         outPorts_[0]->PushData(buffer, -1);
360     }
361 }
362 } // namespace Pipeline
363 } // namespace Media
364 } // namespace OHOS
365 #endif