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