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