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