1 /*
2 * Copyright (c) 2023-2023 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 #if defined(VIDEO_SUPPORT)
16
17 #define HST_LOG_TAG "HdiCodecAdapter"
18
19 #include "hdi_codec_adapter.h"
20 #include <utility>
21 #include "codec_callback_if.h"
22 #include "codec_callback_type_stub.h"
23 #include "codec_component_if.h"
24 #include "codec_utils.h"
25 #include "foundation/log.h"
26 #include "hdf_base.h"
27 #include "hdi_codec_manager.h"
28 #include "plugin/common/plugin_attr_desc.h"
29
30 namespace {
31 using namespace OHOS::Media::Plugin;
32 using namespace CodecAdapter;
RegisterHdiAdapterPlugins(const std::shared_ptr<OHOS::Media::Plugin::Register> & reg)33 Status RegisterHdiAdapterPlugins(const std::shared_ptr<OHOS::Media::Plugin::Register>& reg)
34 {
35 MEDIA_LOG_I("RegisterHdiAdapterPlugins Start");
36 return HdiCodecManager::GetInstance().RegisterCodecPlugins(reg);
37 }
38
UnRegisterHdiAdapterPlugins()39 void UnRegisterHdiAdapterPlugins()
40 {
41 MEDIA_LOG_I("UnRegisterHdiAdapterPlugins Start");
42 HdiCodecManager::GetInstance().UnRegisterCodecPlugins();
43 }
44 } // namespace
45
46 PLUGIN_DEFINITION(CodecAdapter, LicenseType::APACHE_V2, RegisterHdiAdapterPlugins, UnRegisterHdiAdapterPlugins);
47
48 namespace OHOS {
49 namespace Media {
50 namespace Plugin {
51 namespace CodecAdapter {
52 // hdi adapter callback
EventHandler(CodecCallbackType * self,OMX_EVENTTYPE event,EventInfo * info)53 int32_t HdiCodecAdapter::EventHandler(CodecCallbackType* self, OMX_EVENTTYPE event, EventInfo* info)
54 {
55 MEDIA_LOG_I("EventHandler-callback Start, appData: " PUBLIC_LOG_D64 ", eEvent: " PUBLIC_LOG_D32
56 ", nData1: " PUBLIC_LOG_U32 ", nData2: " PUBLIC_LOG_U32,
57 info->appData, static_cast<int>(event), info->data1, info->data2);
58 auto hdiAdapter = reinterpret_cast<HdiCodecAdapter*>(info->appData);
59 hdiAdapter->codecCmdExecutor_->OnEvent(event, info);
60 MEDIA_LOG_D("EventHandler-callback end");
61 return HDF_SUCCESS;
62 }
63
EmptyBufferDone(CodecCallbackType * self,int64_t appData,const OmxCodecBuffer * omxBuffer)64 int32_t HdiCodecAdapter::EmptyBufferDone(CodecCallbackType* self, int64_t appData, const OmxCodecBuffer* omxBuffer)
65 {
66 MEDIA_LOG_DD("EmptyBufferDone begin, bufferId: " PUBLIC_LOG_U32, omxBuffer->bufferId);
67 auto hdiAdapter = reinterpret_cast<HdiCodecAdapter*>(appData);
68 hdiAdapter->inBufPool_->UseBufferDone(omxBuffer->bufferId);
69 if (!hdiAdapter->isFlushing_) {
70 hdiAdapter->HandleFrame();
71 }
72 MEDIA_LOG_DD("EmptyBufferDone-callback end, free in buffer count: " PUBLIC_LOG_U32,
73 hdiAdapter->inBufPool_->EmptyBufferCount());
74 return HDF_SUCCESS;
75 }
76
FillBufferDone(CodecCallbackType * self,int64_t appData,const OmxCodecBuffer * omxBuffer)77 int32_t HdiCodecAdapter::FillBufferDone(CodecCallbackType* self, int64_t appData, const OmxCodecBuffer* omxBuffer)
78 {
79 MEDIA_LOG_DD("FillBufferDone-callback begin, bufferId: " PUBLIC_LOG_U32 ", flag: " PUBLIC_LOG_U32
80 ", pts: " PUBLIC_LOG_D64, omxBuffer->bufferId, omxBuffer->flag, omxBuffer->pts);
81 auto hdiAdapter = reinterpret_cast<HdiCodecAdapter*>(appData);
82 auto codecBuffer = hdiAdapter->outBufPool_->GetBuffer(omxBuffer->bufferId);
83 if (codecBuffer == nullptr) {
84 return HDF_FAILURE;
85 }
86 std::shared_ptr<Plugin::Buffer> outputBuffer = nullptr;
87 (void)codecBuffer->Unbind(outputBuffer, omxBuffer);
88 hdiAdapter->outBufPool_->UseBufferDone(omxBuffer->bufferId);
89 {
90 OSAL::ScopedLock l(hdiAdapter->bufferMetaMutex_);
91 auto iter = hdiAdapter->bufferMetaMap_.find(omxBuffer->pts);
92 if (iter != hdiAdapter->bufferMetaMap_.end()) {
93 outputBuffer->UpdateBufferMeta(*(iter->second));
94 hdiAdapter->bufferMetaMap_.erase(omxBuffer->pts);
95 } else {
96 uint32_t frameNum = 0;
97 outputBuffer->GetBufferMeta()->SetMeta(Tag::USER_FRAME_NUMBER, frameNum);
98 }
99 }
100 if (hdiAdapter->isFlushing_) {
101 MEDIA_LOG_DD("hdi adapter is flushing, ignore this data");
102 outputBuffer = nullptr;
103 return HDF_SUCCESS;
104 }
105 hdiAdapter->NotifyOutputBufferDone(outputBuffer);
106 (void)hdiAdapter->FillAllTheOutBuffer(); // call FillThisBuffer() again
107 MEDIA_LOG_DD("FillBufferDone-callback end, free out buffer count: " PUBLIC_LOG_U32,
108 hdiAdapter->outBufPool_->EmptyBufferCount());
109 return HDF_SUCCESS;
110 }
111
HdiCodecAdapter(std::string componentName,std::string pluginMime)112 HdiCodecAdapter::HdiCodecAdapter(std::string componentName, std::string pluginMime)
113 : CodecPlugin(std::move(componentName)), pluginMime_(std::move(pluginMime))
114 {
115 MEDIA_LOG_I("ctor called");
116 shaAlloc_ = std::make_shared<ShareAllocator>(Plugin::ShareMemType::READ_WRITE_TYPE);
117 }
118
~HdiCodecAdapter()119 HdiCodecAdapter::~HdiCodecAdapter()
120 {
121 MEDIA_LOG_I("dtor called");
122 if (codecCallback_) {
123 CodecCallbackTypeStubRelease(codecCallback_);
124 codecCallback_ = nullptr;
125 }
126 }
127
Init()128 Status HdiCodecAdapter::Init()
129 {
130 MEDIA_LOG_D("Init begin");
131 auto firstDotPos = pluginName_.find_first_of('.'); // pluginName_: HdiCodecAdapter.OMX.rk.video_decoder.avc
132 MEDIA_LOG_D("pluginName_: " PUBLIC_LOG_S, pluginName_.c_str());
133 if (firstDotPos == std::string::npos) {
134 MEDIA_LOG_E("create codec handle error with plugin name " PUBLIC_LOG_S ", which is wrong format",
135 pluginName_.c_str());
136 return Status::ERROR_UNSUPPORTED_FORMAT;
137 }
138 componentName_ = pluginName_.substr(firstDotPos + 1); // ComponentCapability.compName
139 codecCallback_ = CodecCallbackTypeStubGetInstance();
140 FALSE_RETURN_V_MSG(codecCallback_ != nullptr, Status::ERROR_NULL_POINTER, "create callback_ failed");
141
142 codecCallback_->EventHandler = &HdiCodecAdapter::EventHandler;
143 codecCallback_->EmptyBufferDone = &HdiCodecAdapter::EmptyBufferDone;
144 codecCallback_->FillBufferDone = &HdiCodecAdapter::FillBufferDone;
145
146 int32_t ret = HdiCodecManager::GetInstance().CreateComponent(&codecComp_, componentId_,
147 const_cast<char*>(componentName_.c_str()),
148 (int64_t)this, codecCallback_);
149 FALSE_RETURN_V_MSG(codecComp_ != nullptr, Status::ERROR_NULL_POINTER,
150 "create component failed, retVal = " PUBLIC_LOG_D32, (int)ret);
151 FALSE_RETURN_V_MSG(InitVersion() == Status::OK, Status::ERROR_INVALID_DATA, "Init compVersion failed!");
152 FALSE_RETURN_V_MSG(InitPortIndex() == Status::OK, Status::ERROR_INVALID_DATA, "Init compVersion failed!");
153 inCodecPort_ = std::make_shared<CodecPort>(codecComp_, inPortIndex_, verInfo_);
154 outCodecPort_ = std::make_shared<CodecPort>(codecComp_, outPortIndex_, verInfo_);
155 codecCmdExecutor_ = std::make_shared<CodecCmdExecutor>(codecComp_, inPortIndex_);
156 portConfigured_ = false;
157 MEDIA_LOG_D("Init end, component Id = " PUBLIC_LOG_D32, componentId_);
158 return Status::OK;
159 }
160
InitVersion()161 Status HdiCodecAdapter::InitVersion()
162 {
163 (void)memset_s(&verInfo_, sizeof(verInfo_), 0, sizeof(verInfo_));
164 auto ret = codecComp_->GetComponentVersion(codecComp_, &verInfo_);
165 FALSE_RETURN_V_MSG_E(ret == HDF_SUCCESS, Status::ERROR_INVALID_DATA,
166 "get component version failed, ret: " PUBLIC_LOG_D32, ret);
167 return Status::OK;
168 }
169
InitPortIndex()170 Status HdiCodecAdapter::InitPortIndex()
171 {
172 MEDIA_LOG_D("InitPortIndex begin");
173 InitOmxParam(portParam_, verInfo_);
174 auto ret = HdiGetParameter(codecComp_, OMX_IndexParamVideoInit, portParam_);
175 FALSE_RETURN_V_MSG_E(ret == HDF_SUCCESS, Status::ERROR_INVALID_DATA,
176 "Get portParam failed, ret: " PUBLIC_LOG_D32, ret);
177 inPortIndex_ = portParam_.nStartPortNumber;
178 outPortIndex_ = portParam_.nStartPortNumber + 1;
179 MEDIA_LOG_I("inPortIndex: " PUBLIC_LOG_U32 ", outPortIndex: " PUBLIC_LOG_U32, inPortIndex_, outPortIndex_);
180 return Status::OK;
181 }
182
Deinit()183 Status HdiCodecAdapter::Deinit()
184 {
185 MEDIA_LOG_D("DeInit Enter");
186 FALSE_RETURN_V_MSG_E(Reset() == Status::OK, Status::ERROR_INVALID_DATA, "Reset value failed");
187 auto ret = HdiCodecManager::GetInstance().DestroyComponent(codecComp_, componentId_);
188 FALSE_RETURN_V_MSG_E(ret == HDF_SUCCESS, Status::ERROR_INVALID_OPERATION,
189 "HDI destroy component failed, ret = " PUBLIC_LOG_S, HdfStatus2String(ret).c_str());
190 if (codecComp_) {
191 CodecComponentTypeRelease(codecComp_);
192 codecComp_ = nullptr;
193 }
194 if (codecCallback_) {
195 CodecCallbackTypeStubRelease(codecCallback_);
196 codecCallback_ = nullptr;
197 }
198 MEDIA_LOG_D("DeInit End;");
199 return Status::OK;
200 }
201
Prepare()202 Status HdiCodecAdapter::Prepare()
203 {
204 MEDIA_LOG_D("Prepare Start");
205 FALSE_RETURN_V_MSG_E(ChangeState(OMX_StateIdle) == Status::OK, Status::ERROR_WRONG_STATE,
206 "Change omx state to idle failed");
207 outBufQue_->SetActive(true);
208 inBufPool_ = std::make_shared<CodecBufferPool>(codecComp_, verInfo_, inPortIndex_, inBufferCnt_);
209 outBufPool_ = std::make_shared<CodecBufferPool>(codecComp_, verInfo_, outPortIndex_, outBufferCnt_);
210 OHOS::Media::BlockingQueue<std::shared_ptr<Buffer>> inBufQue("TempInBufferQue", inBufferCnt_);
211 for (uint32_t i = 0; i < inBufferCnt_; i++) {
212 auto buf = std::make_shared<Buffer>(BufferMetaType::VIDEO);
213 if (inputMemoryType_ == MemoryType::VIRTUAL_ADDR && !buf->AllocMemory(shaAlloc_, inBufferSize_)) {
214 MEDIA_LOG_E("alloc buffer " PUBLIC_LOG_U32 " fail, i: ", static_cast<uint32_t>(i));
215 }
216 inBufQue.Push(buf);
217 }
218 auto inputMemoryType = MemoryType::SHARE_MEMORY;
219 if (inputMemoryType_ == MemoryType::SURFACE_BUFFER) {
220 inputMemoryType = MemoryType::SURFACE_BUFFER;
221 }
222 bool isInput = true;
223 inBufPool_->UseBuffers(inBufQue, inputMemoryType, isInput, inBufferSize_);
224 outBufPool_->UseBuffers(*outBufQue_, outputMemoryType_, !isInput, outBufferSize_);
225 FALSE_RETURN_V_MSG_E(WaitForState(OMX_StateIdle) == Status::OK, Status::ERROR_WRONG_STATE,
226 "Wait omx state to idle failed");
227 MEDIA_LOG_D("prepare end");
228 return Status::OK;
229 }
230
Reset()231 Status HdiCodecAdapter::Reset()
232 {
233 MEDIA_LOG_D("Reset Start");
234 FALSE_RETURN_V_MSG_E(ChangeState(OMX_StateIdle) == Status::OK,
235 Status::ERROR_WRONG_STATE, "Change omx state to idle failed");
236 FALSE_RETURN_V_MSG_E(WaitForState(OMX_StateIdle) == Status::OK,
237 Status::ERROR_WRONG_STATE, "Wait omx state to idle failed");
238 curState_ = OMX_StateIdle;
239 FALSE_RETURN_V_MSG_E(FreeBuffers() == Status::OK, Status::ERROR_WRONG_STATE, "FreeBuffers failed");
240 outBufQue_->SetActive(false);
241 outBufQue_->Clear();
242 inBufQue_.clear();
243 {
244 OSAL::ScopedLock l(bufferMetaMutex_);
245 bufferMetaMap_.clear();
246 }
247 width_ = 0;
248 height_ = 0;
249 inBufferSize_ = 0;
250 inBufferCnt_ = 0;
251 outBufferSize_= 0;
252 outBufferCnt_ = 0;
253 inputMemoryType_ = MemoryType::VIRTUAL_ADDR;
254 outputMemoryType_ = MemoryType::VIRTUAL_ADDR;
255 return Status::OK;
256 }
257
Start()258 Status HdiCodecAdapter::Start()
259 {
260 MEDIA_LOG_D("start begin");
261 FALSE_RETURN_V_MSG_E(ChangeState(OMX_StateExecuting) == Status::OK,
262 Status::ERROR_WRONG_STATE, "Change omx state to idle failed");
263 FALSE_RETURN_V_MSG_E(WaitForState(OMX_StateExecuting) == Status::OK,
264 Status::ERROR_WRONG_STATE, "Wait omx state to idle failed");
265 curState_ = OMX_StateExecuting;
266 outBufQue_->SetActive(true);
267 if (!FillAllTheOutBuffer()) {
268 MEDIA_LOG_E("Fill all buffer error");
269 return Status::ERROR_UNKNOWN;
270 }
271 MEDIA_LOG_D("start end");
272 return Status::OK;
273 }
274
Stop()275 Status HdiCodecAdapter::Stop()
276 {
277 MEDIA_LOG_D("Stop Enter");
278 outBufQue_->SetActive(false);
279 MEDIA_LOG_D("Stop End");
280 return Status::OK;
281 }
282
Flush()283 Status HdiCodecAdapter::Flush()
284 {
285 MEDIA_LOG_D("Flush begin");
286 isFlushing_ = true;
287 {
288 OSAL::ScopedLock l(lockInputBuffers_);
289 inBufQue_.clear();
290 }
291 // -1: Refresh input and output ports
292 auto ret = codecCmdExecutor_->SendCmd(OMX_CommandFlush, inPortIndex_);
293 FALSE_RETURN_V_MSG_E(ret == Status::OK, Status::ERROR_UNKNOWN, "Flush inPort failed");
294 auto err = codecCmdExecutor_->WaitCmdResult(OMX_CommandFlush, inPortIndex_);
295 FALSE_RETURN_V_MSG_E(err == true, Status::ERROR_UNKNOWN, "Wait flush inPort failed");
296
297 ret = codecCmdExecutor_->SendCmd(OMX_CommandFlush, outPortIndex_);
298 FALSE_RETURN_V_MSG_E(ret == Status::OK, Status::ERROR_UNKNOWN, "Flush outPort failed");
299 err = codecCmdExecutor_->WaitCmdResult(OMX_CommandFlush, outPortIndex_);
300 FALSE_RETURN_V_MSG_E(err == true, Status::ERROR_UNKNOWN, "Wait flush outPort failed");
301 isFlushing_ = false;
302 MEDIA_LOG_D("Flush end");
303 return Status::OK;
304 }
305
GetParameter(Plugin::Tag tag,ValueType & value)306 Status HdiCodecAdapter::GetParameter(Plugin::Tag tag, ValueType &value)
307 {
308 MEDIA_LOG_D("GetParameter begin");
309 switch (tag) {
310 case Tag::REQUIRED_OUT_BUFFER_CNT:
311 if (!outBufferCnt_) {
312 return Status::ERROR_INVALID_DATA;
313 }
314 value = outBufferCnt_;
315 break;
316 case Tag::REQUIRED_OUT_BUFFER_SIZE:
317 if (!outBufferSize_) {
318 return Status::ERROR_INVALID_DATA;
319 }
320 value = outBufferSize_;
321 break;
322 default:
323 MEDIA_LOG_W("ignore this tag: " PUBLIC_LOG_S, Tag2String(tag));
324 break;
325 }
326 return Status::OK;
327 }
328
SetParameter(Plugin::Tag tag,const ValueType & value)329 Status HdiCodecAdapter::SetParameter(Plugin::Tag tag, const ValueType &value)
330 {
331 // When use hdi as codec plugin, must set width & height into hdi,
332 // Hdi use these params to calc out buffer size & count then return to filter
333 MEDIA_LOG_D("SetParameter begin");
334 switch (tag) {
335 case Tag::VIDEO_WIDTH:
336 width_ = Plugin::AnyCast<uint32_t>(value);
337 break;
338 case Tag::VIDEO_HEIGHT:
339 height_ = Plugin::AnyCast<uint32_t>(value);
340 break;
341 case Tag::VIDEO_PIXEL_FORMAT:
342 pixelFormat_ = Plugin::AnyCast<VideoPixelFormat>(value);
343 break;
344 case Tag::VIDEO_FRAME_RATE:
345 frameRate_ = Plugin::AnyCast<uint32_t>(value);
346 break;
347 case Tag::MEDIA_BITRATE:
348 bitRate_ = Plugin::AnyCast<int64_t>(value);
349 break;
350 case Tag::INPUT_MEMORY_TYPE:
351 inputMemoryType_ = Plugin::AnyCast<MemoryType>(value);
352 break;
353 case Tag::OUTPUT_MEMORY_TYPE:
354 outputMemoryType_ = Plugin::AnyCast<MemoryType>(value);
355 break;
356 default:
357 MEDIA_LOG_W("Ignore this tag: " PUBLIC_LOG_S, Tag2String(tag));
358 break;
359 }
360 if (width_ != 0 && height_ != 0 && pixelFormat_ != VideoPixelFormat::UNKNOWN && !portConfigured_ &&
361 frameRate_ != 0) {
362 FALSE_RETURN_V_MSG_E(ConfigOmx() == Status::OK, Status::ERROR_INVALID_OPERATION, "Configure omx failed");
363 }
364 MEDIA_LOG_D("SetParameter end");
365 return Status::OK;
366 }
367
ConfigOmx()368 Status HdiCodecAdapter::ConfigOmx()
369 {
370 MEDIA_LOG_D("ConfigOmx Start");
371 Meta meta;
372 meta.Set<Tag::MIME>(pluginMime_);
373 meta.Set<Tag::VIDEO_WIDTH>(width_);
374 meta.Set<Tag::VIDEO_HEIGHT>(height_);
375 meta.Set<Tag::VIDEO_FRAME_RATE>(frameRate_);
376 meta.Set<Tag::VIDEO_PIXEL_FORMAT>(pixelFormat_);
377 meta.Set<Tag::MEDIA_BITRATE>(bitRate_);
378 auto ret = inCodecPort_->Config(meta);
379 FALSE_RETURN_V_MSG_E(ret == Status::OK, Status::ERROR_INVALID_OPERATION, "Configure inCodecPort failed");
380 ret = outCodecPort_->Config(meta);
381 FALSE_RETURN_V_MSG_E(ret == Status::OK, Status::ERROR_INVALID_OPERATION, "Configure outCodecPort failed");
382 PortInfo portInfo;
383 inCodecPort_->QueryParam(portInfo);
384 inBufferCnt_ = portInfo.bufferCount;
385 inBufferSize_ = portInfo.bufferSize;
386 MEDIA_LOG_D("inBufCnt: " PUBLIC_LOG_D32 ", inBufSize: " PUBLIC_LOG_D32, inBufferCnt_, inBufferSize_);
387 if (!portInfo.enabled) {
388 codecCmdExecutor_->SendCmd(OMX_CommandPortEnable, inPortIndex_);
389 (void) codecCmdExecutor_->WaitCmdResult(OMX_CommandPortEnable, inPortIndex_);
390 }
391 outCodecPort_->QueryParam(portInfo);
392 outBufferCnt_ = portInfo.bufferCount;
393 outBufferSize_ = portInfo.bufferSize;
394 outBufQue_ = std::make_shared<BlockingQueue<std::shared_ptr<Buffer>>>("hdiAdapterOutQueue", outBufferCnt_);
395 MEDIA_LOG_D("outBufCnt: " PUBLIC_LOG_D32 ", outBufSize: " PUBLIC_LOG_D32, outBufferCnt_, outBufferSize_);
396 if (!portInfo.enabled) {
397 codecCmdExecutor_->SendCmd(OMX_CommandPortEnable, outPortIndex_);
398 (void) codecCmdExecutor_->WaitCmdResult(OMX_CommandPortEnable, outPortIndex_);
399 }
400 portConfigured_ = true;
401 return Status::OK;
402 }
403
GetAllocator()404 std::shared_ptr<Plugin::Allocator> HdiCodecAdapter::GetAllocator()
405 {
406 MEDIA_LOG_D("GetAllocator begin");
407 return shaAlloc_;
408 }
409
QueueInputBuffer(const std::shared_ptr<Buffer> & inputBuffer,int32_t timeoutMs)410 Status HdiCodecAdapter::QueueInputBuffer(const std::shared_ptr<Buffer>& inputBuffer, int32_t timeoutMs)
411 {
412 MEDIA_LOG_DD("QueueInputBuffer Start");
413 if (inputBuffer->IsEmpty() && !(inputBuffer->flag & BUFFER_FLAG_EOS)) {
414 MEDIA_LOG_E("empty input buffer without eos flag");
415 return Status::ERROR_INVALID_DATA;
416 }
417 {
418 OSAL::ScopedLock l(lockInputBuffers_);
419 inBufQue_.push_back(inputBuffer);
420 MEDIA_LOG_DD("QueueInputBuffer end, inBufQue_.size: " PUBLIC_LOG_ZU, inBufQue_.size());
421 }
422 if (!isFlushing_) {
423 HandleFrame();
424 }
425 return Status::OK;
426 }
427
428 // 循环从输入buffer队列中取出一个buffer,转换成 omxBuffer 后调用 HDI 的 EmptyThisBuffer() 进行解码
HandleFrame()429 void HdiCodecAdapter::HandleFrame()
430 {
431 MEDIA_LOG_DD("handle frame begin");
432 while (inBufPool_->EmptyBufferCount()) {
433 std::shared_ptr<Buffer> inputBuffer = nullptr;
434 std::shared_ptr<CodecBuffer> codecBuffer = nullptr;
435 {
436 OSAL::ScopedLock l(lockInputBuffers_);
437 if (inBufQue_.empty()) {
438 return;
439 }
440 inputBuffer = inBufQue_.front();
441 codecBuffer = inBufPool_->GetBuffer();
442 FALSE_RETURN(codecBuffer != nullptr);
443 inBufQue_.pop_front();
444 }
445 if (inputMemoryType_ == MemoryType::VIRTUAL_ADDR) {
446 FALSE_RETURN_MSG(codecBuffer->Copy(inputBuffer) == Status::OK, "Copy inBuffer into codecBuffer fail");
447 } else {
448 FALSE_RETURN_MSG(codecBuffer->Rebind(inputBuffer) == Status::OK, "Rebind inBuffer into codecBuffer fail");
449 }
450 {
451 OSAL::ScopedLock l(bufferMetaMutex_);
452 bufferMetaMap_.emplace(inputBuffer->pts, inputBuffer->GetBufferMeta()->Clone());
453 }
454 auto ret = HdiEmptyThisBuffer(codecComp_, codecBuffer->GetOmxBuffer().get());
455 FALSE_LOG_MSG(ret == HDF_SUCCESS, "call EmptyThisBuffer() error, ret: " PUBLIC_LOG_S,
456 HdfStatus2String(ret).c_str());
457 NotifyInputBufferDone(inputBuffer);
458 }
459 MEDIA_LOG_DD("handle frame end");
460 }
461
QueueOutputBuffer(const std::shared_ptr<Buffer> & outputBuffer,int32_t timeoutMs)462 Status HdiCodecAdapter::QueueOutputBuffer(const std::shared_ptr<Buffer>& outputBuffer, int32_t timeoutMs)
463 {
464 MEDIA_LOG_DD("QueueOutputBuffer start, outBufQue size: " PUBLIC_LOG_ZU, outBufQue_->Size());
465 outBufQue_->Push(outputBuffer);
466 if (curState_ == OMX_StateExecuting && !isFlushing_) {
467 FillAllTheOutBuffer();
468 }
469 MEDIA_LOG_DD("QueueOutputBuffer end");
470 return Status::OK;
471 }
472
SetCallback(Callback * cb)473 Status HdiCodecAdapter::SetCallback(Callback* cb)
474 {
475 MEDIA_LOG_D("SetCallback begin");
476 callback_ = cb;
477 codecCmdExecutor_->SetCallback(cb);
478 return Status::OK;
479 }
480
SetDataCallback(DataCallback * dataCallback)481 Status HdiCodecAdapter::SetDataCallback(DataCallback* dataCallback)
482 {
483 MEDIA_LOG_D("SetDataCallback begin");
484 dataCallback_ = dataCallback;
485 return Status::OK;
486 }
487
NotifyInputBufferDone(const std::shared_ptr<Buffer> & input)488 void HdiCodecAdapter::NotifyInputBufferDone(const std::shared_ptr<Buffer>& input)
489 {
490 if (dataCallback_ != nullptr) {
491 dataCallback_->OnInputBufferDone(input);
492 }
493 MEDIA_LOG_DD("NotifyInputBufferDone end");
494 }
495
NotifyOutputBufferDone(const std::shared_ptr<Buffer> & output)496 void HdiCodecAdapter::NotifyOutputBufferDone(const std::shared_ptr<Buffer>& output)
497 {
498 if (dataCallback_ != nullptr) {
499 dataCallback_->OnOutputBufferDone(output);
500 }
501 MEDIA_LOG_DD("NotifyOutputBufferDone end");
502 }
503
FillAllTheOutBuffer()504 bool HdiCodecAdapter::FillAllTheOutBuffer()
505 {
506 OSAL::ScopedLock l(fillAllTheOutBufferMutex_);
507 MEDIA_LOG_DD("FillAllTheBuffer begin");
508 if (isFirstCall_) {
509 MEDIA_LOG_I("isFirstCall: " PUBLIC_LOG_D32, isFirstCall_);
510 isFirstCall_ = false;
511 for (uint32_t i = 0; i < outBufferCnt_; ++i) {
512 auto codecBuffer = outBufPool_->GetBuffer();
513 FALSE_RETURN_V_MSG_E(codecBuffer != nullptr, false, "Get codecBuffer failed");
514 auto ret = HdiFillThisBuffer(codecComp_, codecBuffer->GetOmxBuffer().get());
515 FALSE_RETURN_V_MSG_E(ret == HDF_SUCCESS, false, "Call FillThisBuffer() error, ret: " PUBLIC_LOG_S
516 ", isFirstCall: " PUBLIC_LOG_D32, HdfStatus2String(ret).c_str(), isFirstCall_);
517 }
518 } else {
519 while (!outBufQue_->Empty()) {
520 if (!outBufPool_->EmptyBufferCount()) {
521 MEDIA_LOG_D("outBufQue_ have data, but freeBufferId is empty");
522 return false;
523 }
524 auto codecBuffer = outBufPool_->GetBuffer();
525 FALSE_RETURN_V(codecBuffer != nullptr, false);
526 auto outputBuffer = outBufQue_->Pop(1);
527 if (outputBuffer == nullptr) {
528 MEDIA_LOG_E("output buffer is nullptr");
529 outBufPool_->UseBufferDone(codecBuffer->GetBufferId());
530 return false;
531 }
532 codecBuffer->Rebind(outputBuffer); // 这里outBuf需要保存到codecBuffer里面,方便往下一节点传数据
533 auto ret = HdiFillThisBuffer(codecComp_, codecBuffer->GetOmxBuffer().get());
534 if (ret != HDF_SUCCESS) {
535 codecBuffer->Unbind(outputBuffer, codecBuffer->GetOmxBuffer().get());
536 outBufPool_->UseBufferDone(codecBuffer->GetBufferId());
537 MEDIA_LOG_E("Call FillThisBuffer() error, ret: " PUBLIC_LOG_S ", isFirstCall: " PUBLIC_LOG_D32,
538 HdfStatus2String(ret).c_str(), isFirstCall_);
539 }
540 }
541 }
542 MEDIA_LOG_DD("FillAllTheBuffer end, free out bufferId count: " PUBLIC_LOG_U32 ", outBufQue_->Size: " PUBLIC_LOG_ZU,
543 outBufPool_->EmptyBufferCount(), outBufQue_->Size());
544 return true;
545 }
546
FreeBuffers()547 Status HdiCodecAdapter::FreeBuffers()
548 {
549 MEDIA_LOG_D("FreeBuffers begin");
550 FALSE_RETURN_V_MSG_E(ChangeState(OMX_StateLoaded) == Status::OK,
551 Status::ERROR_WRONG_STATE, "Change omx state to loaded failed");
552 auto val = inBufPool_->FreeBuffers();
553 FALSE_RETURN_V_MSG_E(val == Status::OK, val, "free buffers failed");
554 val = outBufPool_->FreeBuffers();
555 FALSE_RETURN_V_MSG_E(val == Status::OK, val, "free buffers failed");
556 FALSE_RETURN_V_MSG_E(WaitForState(OMX_StateLoaded) == Status::OK,
557 Status::ERROR_WRONG_STATE, "Wait omx state to loaded failed");
558 curState_ = OMX_StateLoaded;
559 return Status::OK;
560 }
561
ChangeState(OMX_STATETYPE state)562 Status HdiCodecAdapter::ChangeState(OMX_STATETYPE state)
563 {
564 MEDIA_LOG_I("change state from " PUBLIC_LOG_S " to " PUBLIC_LOG_S,
565 OmxStateToString(targetState_).c_str(), OmxStateToString(state).c_str());
566 if (targetState_ != state && curState_ != state) {
567 auto ret = codecCmdExecutor_->SendCmd(OMX_CommandStateSet, state);
568 FALSE_RETURN_V_MSG(ret == Status::OK, Status::ERROR_INVALID_OPERATION, "HdiSendCommand failed");
569 targetState_ = state;
570 }
571 return Status::OK;
572 }
573
WaitForState(OMX_STATETYPE state)574 Status HdiCodecAdapter::WaitForState(OMX_STATETYPE state)
575 {
576 MEDIA_LOG_D("WaitForState begin");
577 auto ret = codecCmdExecutor_->WaitCmdResult(OMX_CommandStateSet, state);
578 if (!ret) {
579 MEDIA_LOG_E("Wait state failed");
580 return Status::ERROR_WRONG_STATE;
581 }
582 curState_ = state;
583 MEDIA_LOG_D("WaitForState end");
584 return Status::OK;
585 }
586 } // namespace CodecAdapter
587 } // namespace Plugin
588 } // namespace Media
589 } // namespace OHOS
590 #endif