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