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