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