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