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 "VideoEncoderFilter"
19 
20 #include "pipeline/filters/codec/video_encoder/video_encoder_filter.h"
21 #include "foundation/cpp_ext/memory_ext.h"
22 #include "foundation/log.h"
23 #include "foundation/osal/utils/util.h"
24 #include "foundation/utils/constants.h"
25 #include "foundation/utils/steady_clock.h"
26 #include "pipeline/factory/filter_factory.h"
27 #include "plugin/common/plugin_attr_desc.h"
28 #include "plugin/common/plugin_buffer.h"
29 #include "plugin/common/plugin_video_tags.h"
30 
31 namespace OHOS {
32 namespace Media {
33 namespace Pipeline {
34 const uint32_t DEFAULT_IN_BUFFER_POOL_SIZE = 8;
35 const uint32_t DEFAULT_OUT_BUFFER_POOL_SIZE = 8;
36 const float VIDEO_PIX_DEPTH = 1.5;
37 static uint32_t VIDEO_ALIGN_SIZE = 16;
38 static uint32_t DEFAULT_TRY_DECODE_TIME = 10;
39 
40 static AutoRegisterFilter<VideoEncoderFilter> g_registerFilterHelper("builtin.recorder.videoencoder");
41 
42 class VideoEncoderFilter::DataCallbackImpl : public Plugin::DataCallbackHelper {
43 public:
DataCallbackImpl(VideoEncoderFilter & filter)44     explicit DataCallbackImpl(VideoEncoderFilter& filter) : encFilter_(filter)
45     {
46     }
47 
48     ~DataCallbackImpl() override = default;
49 
OnInputBufferDone(const std::shared_ptr<Plugin::Buffer> & input)50     void OnInputBufferDone(const std::shared_ptr<Plugin::Buffer>& input) override
51     {
52         encFilter_.OnInputBufferDone(input);
53     }
54 
OnOutputBufferDone(const std::shared_ptr<Plugin::Buffer> & output)55     void OnOutputBufferDone(const std::shared_ptr<Plugin::Buffer>& output) override
56     {
57         encFilter_.OnOutputBufferDone(output);
58     }
59 
60 private:
61     VideoEncoderFilter& encFilter_;
62 };
63 
VideoEncoderFilter(const std::string & name)64 VideoEncoderFilter::VideoEncoderFilter(const std::string& name)
65     : CodecFilterBase(name), dataCallback_(new DataCallbackImpl(*this))
66 {
67     MEDIA_LOG_I("video encoder ctor called");
68     filterType_ = FilterType::VIDEO_ENCODER;
69     pluginType_ = Plugin::PluginType::VIDEO_ENCODER;
70     vencFormat_.width = 0;
71     vencFormat_.height = 0;
72     vencFormat_.bitRate = -1;
73     vencFormat_.format = Plugin::VideoPixelFormat::YUV420P;
74     vencFormat_.profile = Plugin::VideoH264Profile::UNKNOWN;
75     vencFormat_.frameRate = 0;
76     vencFormat_.level = 0;
77 }
78 
~VideoEncoderFilter()79 VideoEncoderFilter::~VideoEncoderFilter()
80 {
81     MEDIA_LOG_I("video encoder dtor called");
82     isStop_ = true;
83     if (plugin_) {
84         plugin_->Stop();
85         plugin_->Deinit();
86     }
87     if (handleFrameTask_) {
88         handleFrameTask_->Stop();
89         handleFrameTask_.reset();
90     }
91     if (inBufQue_) {
92         inBufQue_->SetActive(false);
93         inBufQue_.reset();
94     }
95     if (pushTask_) {
96         pushTask_->Stop();
97         pushTask_.reset();
98     }
99     if (outBufQue_) {
100         outBufQue_->SetActive(false);
101         outBufQue_.reset();
102     }
103     if (dataCallback_) {
104         delete dataCallback_;
105         dataCallback_ = nullptr;
106     }
107 }
108 
Start()109 ErrorCode VideoEncoderFilter::Start()
110 {
111     MEDIA_LOG_D("video encoder start called");
112     if (state_ != FilterState::READY && state_ != FilterState::PAUSED) {
113         MEDIA_LOG_W("call encoder start() when state_ is not ready or working");
114         return ErrorCode::ERROR_INVALID_OPERATION;
115     }
116     isStop_ = false;
117     return FilterBase::Start();
118 }
119 
Prepare()120 ErrorCode VideoEncoderFilter::Prepare()
121 {
122     MEDIA_LOG_D("video encoder prepare called");
123     if (state_ != FilterState::INITIALIZED) {
124         MEDIA_LOG_W("encoder filter is not in init state_");
125         return ErrorCode::ERROR_INVALID_OPERATION;
126     }
127     if (!outBufQue_) {
128         outBufQue_ = std::make_shared<BlockingQueue<AVBufferPtr>>("vdecFilterOutBufQue", DEFAULT_OUT_BUFFER_POOL_SIZE);
129     } else {
130         outBufQue_->SetActive(true);
131     }
132     if (!pushTask_) {
133         pushTask_ = std::make_shared<OSAL::Task>("vecPushThread");
134         pushTask_->RegisterHandler([this] { FinishFrame(); });
135     }
136     if (!inBufQue_) {
137         inBufQue_ = std::make_shared<BlockingQueue<AVBufferPtr>>("vecFilterInBufQue", DEFAULT_IN_BUFFER_POOL_SIZE);
138     } else {
139         inBufQue_->SetActive(true);
140     }
141     if (!handleFrameTask_) {
142         handleFrameTask_ = std::make_shared<OSAL::Task>("vecHandleFrameThread");
143         handleFrameTask_->RegisterHandler([this] { HandleFrame(); });
144     }
145     return FilterBase::Prepare();
146 }
147 
SetVideoEncoder(int32_t sourceId,std::shared_ptr<Plugin::Meta> encoderMeta)148 ErrorCode VideoEncoderFilter::SetVideoEncoder(int32_t sourceId, std::shared_ptr<Plugin::Meta> encoderMeta)
149 {
150     std::string mime;
151     FALSE_RETURN_V_MSG_E(encoderMeta->Get<Plugin::Tag::MIME>(mime), ErrorCode::ERROR_INVALID_PARAMETER_VALUE,
152                          "Encoder meta must contains mime");
153     vencFormat_.mime = mime;
154     codecMeta_ = std::move(encoderMeta);
155     return ErrorCode::SUCCESS;
156 }
157 
Negotiate(const std::string & inPort,const std::shared_ptr<const Plugin::Capability> & upstreamCap,Plugin::Capability & negotiatedCap,const Plugin::Meta & upstreamParams,Plugin::Meta & downstreamParams)158 bool VideoEncoderFilter::Negotiate(const std::string& inPort,
159                                    const std::shared_ptr<const Plugin::Capability>& upstreamCap,
160                                    Plugin::Capability& negotiatedCap,
161                                    const Plugin::Meta& upstreamParams,
162                                    Plugin::Meta& downstreamParams)
163 {
164     PROFILE_BEGIN("video encoder negotiate start");
165     if (state_ != FilterState::PREPARING) {
166         MEDIA_LOG_W("encoder filter is not in preparing when negotiate");
167         return false;
168     }
169     auto targetOutPort = GetRouteOutPort(inPort);
170     FALSE_RETURN_V_MSG_E(targetOutPort != nullptr, false, "out port not found");
171     std::shared_ptr<Plugin::PluginInfo> selectedPluginInfo = nullptr;
172     bool atLeastOutCapMatched = false;
173     auto candidatePlugins = FindAvailablePlugins(*upstreamCap, pluginType_, preferredCodecMode_);
174     for (const auto& candidate : candidatePlugins) {
175         FALSE_LOG_MSG(!candidate.first->outCaps.empty(), "encoder plugin must have out caps");
176         for (const auto& outCap : candidate.first->outCaps) { // each codec plugin should have at least one out cap
177             Plugin::Meta tmpMeta;
178             if (outCap.mime != vencFormat_.mime ||
179                 !MergeMetaWithCapability(*codecMeta_, outCap, tmpMeta)) {
180                 continue;
181             }
182             auto thisOut = std::make_shared<Plugin::Capability>();
183             if (!MergeCapabilityKeys(*upstreamCap, outCap, *thisOut)) {
184                 MEDIA_LOG_I("one cap of plugin " PUBLIC_LOG_S " mismatch upstream cap", candidate.first->name.c_str());
185                 continue;
186             }
187             atLeastOutCapMatched = true;
188             thisOut->mime = outCap.mime;
189             if (targetOutPort->Negotiate(thisOut, capNegWithDownstream_, upstreamParams, downstreamParams)) {
190                 capNegWithUpstream_ = candidate.second;
191                 selectedPluginInfo = candidate.first;
192                 MEDIA_LOG_I("use plugin " PUBLIC_LOG_S, candidate.first->name.c_str());
193                 MEDIA_LOG_I("neg upstream cap " PUBLIC_LOG_S, Capability2String(capNegWithUpstream_).c_str());
194                 MEDIA_LOG_I("neg downstream cap " PUBLIC_LOG_S, Capability2String(capNegWithDownstream_).c_str());
195                 break;
196             }
197         }
198         if (selectedPluginInfo != nullptr) {
199             break;
200         }
201     }
202     FALSE_RETURN_V_MSG_E(atLeastOutCapMatched && selectedPluginInfo != nullptr, false,
203                          "can't find available encoder plugin with " PUBLIC_LOG_S,
204                          Capability2String(*upstreamCap).c_str());
205     auto res = UpdateAndInitPluginByInfo<Plugin::Codec>(plugin_, pluginInfo_, selectedPluginInfo,
206         [this](const std::string& name)-> std::shared_ptr<Plugin::Codec> {
207         return Plugin::PluginManager::Instance().CreateCodecPlugin(name, pluginType_);
208     });
209     negotiatedCap = *upstreamCap;
210     PROFILE_END("video encoder negotiate end");
211     return res;
212 }
213 
Configure(const std::string & inPort,const std::shared_ptr<const Plugin::Meta> & upstreamMeta,Plugin::Meta & upstreamParams,Plugin::Meta & downstreamParams)214 bool VideoEncoderFilter::Configure(const std::string& inPort, const std::shared_ptr<const Plugin::Meta>& upstreamMeta,
215                                    Plugin::Meta& upstreamParams, Plugin::Meta& downstreamParams)
216 {
217     PROFILE_BEGIN("video encoder configure start");
218     MEDIA_LOG_I("receive upstream meta " PUBLIC_LOG_S, Meta2String(*upstreamMeta).c_str());
219     if (plugin_ == nullptr || pluginInfo_ == nullptr) {
220         MEDIA_LOG_E("cannot configure encoder when no plugin available");
221         return false;
222     }
223     auto thisMeta = std::make_shared<Plugin::Meta>();
224     if (!MergeMetaWithCapability(*upstreamMeta, pluginInfo_->outCaps[0], *thisMeta)) {
225         MEDIA_LOG_E("cannot configure encoder plugin since meta is not compatible with negotiated caps");
226         return false;
227     }
228     auto targetOutPort = GetRouteOutPort(inPort);
229     if (targetOutPort == nullptr) {
230         MEDIA_LOG_E("encoder out port is not found");
231         return false;
232     }
233     auto err = ConfigureNoLocked(thisMeta);
234     if (err != ErrorCode::SUCCESS) {
235         MEDIA_LOG_E("encoder configure error");
236         Event event {
237             .srcFilter = name_,
238             .type = EventType::EVENT_ERROR,
239             .param = err,
240         };
241         OnEvent(event);
242         return false;
243     }
244     FAIL_LOG(UpdateMetaFromPlugin(*thisMeta));
245     if (!targetOutPort->Configure(thisMeta, upstreamParams, downstreamParams)) {
246         MEDIA_LOG_E("encoder filter downstream Configure failed");
247         return false;
248     }
249     state_ = FilterState::READY;
250     Event event {
251         .srcFilter = name_,
252         .type = EventType::EVENT_READY,
253     };
254     OnEvent(event);
255     MEDIA_LOG_I("video encoder send EVENT_READY");
256     PROFILE_END("video encoder configure end");
257     return true;
258 }
259 
AllocateOutputBuffers()260 ErrorCode VideoEncoderFilter::AllocateOutputBuffers()
261 {
262     uint32_t bufferCnt = 0;
263     if (GetPluginParameterLocked(Tag::REQUIRED_OUT_BUFFER_CNT, bufferCnt) != ErrorCode::SUCCESS) {
264         bufferCnt = DEFAULT_OUT_BUFFER_POOL_SIZE;
265     }
266     outBufPool_ = std::make_shared<BufferPool<AVBuffer>>(bufferCnt);
267     uint32_t bufferSize = 0;
268     if (GetPluginParameterLocked(Tag::REQUIRED_OUT_BUFFER_SIZE, bufferSize) != ErrorCode::SUCCESS) {
269         bufferSize = CalculateBufferSize(nullptr);
270     }
271     auto outAllocator = plugin_->GetAllocator(); // zero copy need change to use sink allocator
272     if (outAllocator == nullptr) {
273         MEDIA_LOG_I("plugin doest not support out allocator, using framework allocator");
274         plugin_->SetParameter(Tag::OUTPUT_MEMORY_TYPE, MemoryType::VIRTUAL_ADDR);
275         outBufPool_->Init(bufferSize, Plugin::BufferMetaType::VIDEO);
276     } else {
277         MEDIA_LOG_I("using plugin output allocator");
278         plugin_->SetParameter(Tag::OUTPUT_MEMORY_TYPE, outAllocator->GetMemoryType());
279         for (size_t cnt = 0; cnt < bufferCnt; cnt++) {
280             auto buf = CppExt::make_unique<AVBuffer>(Plugin::BufferMetaType::VIDEO);
281             buf->AllocMemory(outAllocator, bufferSize);
282             outBufPool_->Append(std::move(buf));
283         }
284     }
285     return ErrorCode::SUCCESS;
286 }
287 
CalculateBufferSize(const std::shared_ptr<const Plugin::Meta> & meta)288 uint32_t VideoEncoderFilter::CalculateBufferSize(const std::shared_ptr<const Plugin::Meta>& meta)
289 {
290     (void)meta;
291     uint32_t bufferSize = vencFormat_.width * vencFormat_.height;
292 
293     // YUV420: size = stride * height * 1.5
294     uint32_t stride = Plugin::AlignUp(vencFormat_.width, VIDEO_ALIGN_SIZE);
295     if (vencFormat_.format == Plugin::VideoPixelFormat::YUV420P ||
296         vencFormat_.format == Plugin::VideoPixelFormat::NV21 ||
297         vencFormat_.format == Plugin::VideoPixelFormat::NV12) {
298         bufferSize = static_cast<uint32_t>(Plugin::AlignUp(stride, VIDEO_ALIGN_SIZE) *
299                                            Plugin::AlignUp(vencFormat_.height, VIDEO_ALIGN_SIZE) * VIDEO_PIX_DEPTH);
300         MEDIA_LOG_D("Output buffer size: " PUBLIC_LOG_U32, bufferSize);
301     } else {
302         // need to check video sink support and calc buffer size
303         MEDIA_LOG_E("Unsupported video pixel format: " PUBLIC_LOG_S,
304             Plugin::GetVideoPixelFormatNameStr(vencFormat_.format));
305     }
306     return bufferSize;
307 }
308 
SetVideoEncoderFormat(const std::shared_ptr<const Plugin::Meta> & meta)309 ErrorCode VideoEncoderFilter::SetVideoEncoderFormat(const std::shared_ptr<const Plugin::Meta> &meta)
310 {
311     FALSE_LOG(meta->Get<Plugin::Tag::VIDEO_PIXEL_FORMAT>(vencFormat_.format));
312     FALSE_LOG(meta->Get<Plugin::Tag::VIDEO_WIDTH>(vencFormat_.width));
313     FALSE_LOG(meta->Get<Plugin::Tag::VIDEO_HEIGHT>(vencFormat_.height));
314     FALSE_LOG(meta->Get<Plugin::Tag::MEDIA_BITRATE>(vencFormat_.bitRate));
315     FALSE_LOG(meta->Get<Plugin::Tag::VIDEO_FRAME_RATE>(vencFormat_.frameRate));
316     FALSE_LOG(meta->Get<Plugin::Tag::MIME>(vencFormat_.mime));
317     FALSE_LOG(meta->Get<Plugin::Tag::MEDIA_CODEC_CONFIG>(vencFormat_.codecConfig));
318     return ErrorCode::SUCCESS;
319 }
320 
ConfigurePluginParams()321 ErrorCode VideoEncoderFilter::ConfigurePluginParams()
322 {
323     FALSE_RETURN_V_MSG_W(SetPluginParameterLocked(Tag::VIDEO_WIDTH, vencFormat_.width) == ErrorCode::SUCCESS,
324                          ErrorCode::ERROR_UNKNOWN, "Set width to plugin fail");
325     FALSE_RETURN_V_MSG_W(SetPluginParameterLocked(Tag::VIDEO_HEIGHT, vencFormat_.height) == ErrorCode::SUCCESS,
326                          ErrorCode::ERROR_UNKNOWN, "Set height to plugin fail");
327     FALSE_RETURN_V_MSG_W(SetPluginParameterLocked(Tag::VIDEO_PIXEL_FORMAT, vencFormat_.format) == ErrorCode::SUCCESS,
328                          ErrorCode::ERROR_UNKNOWN, "Set pixel format to plugin fail");
329     if (vencFormat_.bitRate > 0) {
330         auto ret = SetPluginParameterLocked(Tag::MEDIA_BITRATE, vencFormat_.bitRate);
331         FALSE_RETURN_V_MSG_W(ret == ErrorCode::SUCCESS, ErrorCode::ERROR_UNKNOWN,
332                              "Set bitrate to plugin fail");
333     }
334     if (vencFormat_.frameRate > 0) {
335         auto ret = SetPluginParameterLocked(Tag::VIDEO_FRAME_RATE, vencFormat_.frameRate);
336         FALSE_RETURN_V_MSG_W(ret == ErrorCode::SUCCESS, ErrorCode::ERROR_UNKNOWN,
337                              "Set framerate to plugin fail");
338     }
339     if (vencFormat_.mime == MEDIA_MIME_VIDEO_H264) {
340         if (codecMeta_->Get<Plugin::Tag::VIDEO_H264_PROFILE>(vencFormat_.profile)) {
341             auto ret = SetPluginParameterLocked(Tag::VIDEO_H264_PROFILE, vencFormat_.profile);
342             FALSE_RETURN_V_MSG_W(ret == ErrorCode::SUCCESS, ErrorCode::ERROR_UNKNOWN,
343                                  "Set profile to plugin fail");
344         } else {
345             MEDIA_LOG_W("Get VIDEO_H264_PROFILE, fail");
346         }
347         if (codecMeta_->Get<Plugin::Tag::VIDEO_H264_LEVEL>(vencFormat_.level)) {
348             auto ret = SetPluginParameterLocked(Tag::VIDEO_H264_LEVEL, vencFormat_.level);
349             FALSE_RETURN_V_MSG_W(ret == ErrorCode::SUCCESS, ErrorCode::ERROR_UNKNOWN,
350                                  "Set level to plugin fail");
351         } else {
352             MEDIA_LOG_W("Get VIDEO_H264_LEVEL, failed.");
353         }
354     }
355     // Optional: codec extra data
356     if (vencFormat_.codecConfig.size() > 0) {
357         if (SetPluginParameterLocked(Tag::MEDIA_CODEC_CONFIG, std::move(vencFormat_.codecConfig)) !=
358             ErrorCode::SUCCESS) {
359             MEDIA_LOG_W("Set extradata to plugin fail");
360         }
361     }
362     MEDIA_LOG_D("ConfigurePluginParams success, mime: " PUBLIC_LOG_S ", width: " PUBLIC_LOG_U32 ", height: "
363                 PUBLIC_LOG_U32 ", format: " PUBLIC_LOG_S ", bitRate: " PUBLIC_LOG_D64 ", frameRate: " PUBLIC_LOG_U32,
364                 vencFormat_.mime.c_str(), vencFormat_.width, vencFormat_.height,
365                 Plugin::GetVideoPixelFormatNameStr(vencFormat_.format), vencFormat_.bitRate, vencFormat_.frameRate);
366     return ErrorCode::SUCCESS;
367 }
368 
ConfigurePluginOutputBuffers()369 ErrorCode VideoEncoderFilter::ConfigurePluginOutputBuffers()
370 {
371     ErrorCode err = ErrorCode::SUCCESS;
372     while (!outBufPool_->Empty()) {
373         auto ptr = outBufPool_->AllocateBuffer();
374         if (ptr == nullptr) {
375             MEDIA_LOG_W("cannot allocate buffer in buffer pool");
376             continue;
377         }
378         err = TranslatePluginStatus(plugin_->QueueOutputBuffer(ptr, -1));
379         if (err != ErrorCode::SUCCESS) {
380             MEDIA_LOG_E("queue output buffer error");
381         }
382     }
383     return err;
384 }
385 
ConfigurePlugin()386 ErrorCode VideoEncoderFilter::ConfigurePlugin()
387 {
388     FAIL_RETURN_MSG(TranslatePluginStatus(plugin_->SetDataCallback(dataCallback_)),
389         "Set plugin callback fail");
390     FAIL_RETURN_MSG(ConfigurePluginOutputBuffers(), "Configure plugin output buffers error");
391     FAIL_RETURN_MSG(TranslatePluginStatus(plugin_->Prepare()), "Prepare plugin fail");
392     return TranslatePluginStatus(plugin_->Start());
393 }
394 
ConfigureNoLocked(const std::shared_ptr<const Plugin::Meta> & meta)395 ErrorCode VideoEncoderFilter::ConfigureNoLocked(const std::shared_ptr<const Plugin::Meta>& meta)
396 {
397     MEDIA_LOG_D("video encoder configure called");
398     FAIL_RETURN_MSG(SetVideoEncoderFormat(meta), "Set video encoder format fail");
399     FAIL_RETURN_MSG(ConfigurePluginParams(), "Configure plugin params error");
400     FAIL_RETURN_MSG(AllocateOutputBuffers(), "Alloc output buffers fail");
401     FAIL_RETURN_MSG(ConfigurePlugin(), "Config plugin fail");
402     if (handleFrameTask_) {
403         handleFrameTask_->Start();
404     }
405     if (pushTask_) {
406         pushTask_->Start();
407     }
408     return ErrorCode::SUCCESS;
409 }
410 
PushData(const std::string & inPort,const AVBufferPtr & buffer,int64_t offset)411 ErrorCode VideoEncoderFilter::PushData(const std::string& inPort, const AVBufferPtr& buffer, int64_t offset)
412 {
413     if (state_ != FilterState::READY && state_ != FilterState::PAUSED && state_ != FilterState::RUNNING) {
414         MEDIA_LOG_W("pushing data to encoder when state_ is " PUBLIC_LOG_D32, static_cast<int>(state_.load()));
415         return ErrorCode::ERROR_INVALID_OPERATION;
416     }
417     if (isFlushing_) {
418         MEDIA_LOG_I("encoder is flushing, discarding this data from port " PUBLIC_LOG_S, inPort.c_str());
419         return ErrorCode::SUCCESS;
420     }
421     inBufQue_->Push(buffer);
422     return ErrorCode::SUCCESS;
423 }
424 
FlushStart()425 void VideoEncoderFilter::FlushStart()
426 {
427     MEDIA_LOG_I("FlushStart entered");
428     isFlushing_ = true;
429     if (inBufQue_) {
430         inBufQue_->SetActive(false);
431     }
432     if (handleFrameTask_) {
433         handleFrameTask_->PauseAsync();
434     }
435     if (outBufQue_) {
436         outBufQue_->SetActive(false);
437     }
438     if (pushTask_) {
439         pushTask_->PauseAsync();
440     }
441     if (plugin_ != nullptr) {
442         auto err = TranslatePluginStatus(plugin_->Flush());
443         if (err != ErrorCode::SUCCESS) {
444             MEDIA_LOG_E("encoder plugin flush error");
445         }
446     }
447 }
448 
FlushEnd()449 void VideoEncoderFilter::FlushEnd()
450 {
451     MEDIA_LOG_I("FlushEnd entered");
452     isFlushing_ = false;
453     if (inBufQue_) {
454         inBufQue_->SetActive(true);
455     }
456     if (handleFrameTask_) {
457         handleFrameTask_->Start();
458     }
459     if (outBufQue_) {
460         outBufQue_->SetActive(true);
461     }
462     if (pushTask_) {
463         pushTask_->Start();
464     }
465     if (plugin_) {
466         ConfigurePluginOutputBuffers();
467     }
468 }
469 
Stop()470 ErrorCode VideoEncoderFilter::Stop()
471 {
472     FALSE_RETURN_V_MSG_W(plugin_!= nullptr, ErrorCode::ERROR_NULL_POINTER, "plugin is null");
473     FAIL_RETURN_MSG(TranslatePluginStatus(plugin_->Flush()), "Flush plugin fail");
474     FAIL_RETURN_MSG(TranslatePluginStatus(plugin_->Stop()), "Stop plugin fail");
475     isStop_ = true;
476     outBufQue_->SetActive(false);
477     if (pushTask_) {
478         pushTask_->Pause();
479     }
480     inBufQue_->SetActive(false);
481     if (handleFrameTask_) {
482         handleFrameTask_->Pause();
483     }
484     outBufPool_.reset();
485     MEDIA_LOG_I("Stop success");
486     return FilterBase::Stop();
487 }
488 
HandleFrame()489 void VideoEncoderFilter::HandleFrame()
490 {
491     MEDIA_LOG_D("HandleFrame called");
492     auto oneBuffer = inBufQue_->Pop();
493     if (oneBuffer == nullptr) {
494         MEDIA_LOG_W("encoder find nullptr in esBufferQ");
495         return;
496     }
497     HandleOneFrame(oneBuffer);
498 }
499 
HandleOneFrame(const std::shared_ptr<AVBuffer> & data)500 void VideoEncoderFilter::HandleOneFrame(const std::shared_ptr<AVBuffer>& data)
501 {
502     MEDIA_LOG_D("HandleOneFrame called");
503     Plugin::Status ret;
504     do {
505         if (isStop_ || isFlushing_) {
506             MEDIA_LOG_D("filter stop, exit...");
507             break;
508         }
509         ret = plugin_->QueueInputBuffer(data, -1);
510         if (ret == Plugin::Status::OK) {
511             break;
512         }
513         MEDIA_LOG_DD("Send data to plugin error: " PUBLIC_LOG_D32, ret);
514         OSAL::SleepFor(DEFAULT_TRY_DECODE_TIME);
515     } while (1);
516 }
517 
FinishFrame()518 void VideoEncoderFilter::FinishFrame()
519 {
520     MEDIA_LOG_D("begin finish frame");
521     auto ptr = outBufQue_->Pop();
522     if (ptr) {
523         auto oPort = outPorts_[0];
524         if (oPort->GetWorkMode() == WorkMode::PUSH) {
525             oPort->PushData(ptr, -1);
526         } else {
527             MEDIA_LOG_W("encoder out port works in pull mode");
528         }
529         ptr.reset();
530         auto oPtr = outBufPool_->AllocateBuffer();
531         if (oPtr != nullptr) {
532             oPtr->Reset();
533             plugin_->QueueOutputBuffer(oPtr, 0);
534         }
535     }
536     MEDIA_LOG_D("end finish frame");
537 }
538 
OnInputBufferDone(const std::shared_ptr<Plugin::Buffer> & buffer)539 void VideoEncoderFilter::OnInputBufferDone(const std::shared_ptr<Plugin::Buffer>& buffer)
540 {
541     // do nothing since we has no input buffer pool
542 }
543 
OnOutputBufferDone(const std::shared_ptr<Plugin::Buffer> & buffer)544 void VideoEncoderFilter::OnOutputBufferDone(const std::shared_ptr<Plugin::Buffer>& buffer)
545 {
546     outBufQue_->Push(buffer);
547 }
548 } // namespace Pipeline
549 } // namespace Media
550 } // namespace OHOS
551 #endif