• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-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 
16 #include "codec_hdi_adapter_decode.h"
17 #include <dlfcn.h>
18 #include <osal_time.h>
19 #include <sys/mman.h>
20 #include <unistd.h>
21 #include <chrono>
22 #include <sys/stat.h>
23 #include "codec_type.h"
24 #include "codec_omx_ext.h"
25 
26 using namespace std;
27 using namespace OHOS;
28 namespace {
29     constexpr int32_t FD_SIZE = sizeof(int);
30     constexpr int32_t FRAME = (30 << 16);
31     constexpr const char *DECODER_AVC = "rk.video_decoder.avc";
32     constexpr const char *DECODER_HEVC = "rk.video_decoder.hevc";
33     constexpr int32_t START_CODE_OFFSET_ONE = -1;
34     constexpr int32_t START_CODE_OFFSET_SEC = -2;
35     constexpr int32_t START_CODE_OFFSET_THIRD = -3;
36     constexpr int32_t START_CODE_SIZE_FRAME = 4;
37     constexpr int32_t START_CODE_SIZE_SLICE = 3;
38     constexpr int32_t START_CODE = 1;
39     constexpr int32_t USLEEP_TIME = 10000;
40     constexpr int32_t FRAME_SIZE_OPERATOR = 2;
41     constexpr int32_t FRAME_SIZE_MULTI = 3;
42 }
43 
44 #define HDF_LOG_TAG codec_omx_hdi_dec
45 
46 #define AV_COLOR_FORMAT OMX_COLOR_FormatYUV420SemiPlanar
47 
48 static CodecHdiAdapterDecode *g_core = nullptr;
CodecHdiAdapterDecode()49 CodecHdiAdapterDecode::CodecHdiAdapterDecode() : fpIn_(nullptr), fpOut_(nullptr)
50 {
51     client_ = nullptr;
52     callback_ = nullptr;
53     omxMgr_ = nullptr;
54     exit_ = false;
55     width_ = 0;
56     height_ = 0;
57     codecMime_ = codecMime::AVC;
58     count_ = 0;
59     useBufferHandle_ = false;
60     componentId_ = 0;
61     inputBufferSize_ = 0;
62     needSplit_ = 0;
63     srcFileSize_ = 0;
64     totalSrcSize_ = 0;
65 }
66 
~CodecHdiAdapterDecode()67 CodecHdiAdapterDecode::~CodecHdiAdapterDecode()
68 {
69     if (fpOut_ != nullptr) {
70         fclose(fpOut_);
71         fpOut_ = nullptr;
72     }
73 
74     if (fpIn_ != nullptr) {
75         fclose(fpIn_);
76         fpIn_ = nullptr;
77     }
78 }
79 
WaitForStatusChanged()80 void CodecHdiAdapterDecode::WaitForStatusChanged()
81 {
82     unique_lock<mutex> autoLock(statusLock_);
83     statusCondition_.wait(autoLock);
84 }
85 
OnStatusChanged()86 void CodecHdiAdapterDecode::OnStatusChanged()
87 {
88     statusCondition_.notify_one();
89 }
90 
DumpOutputToFile(FILE * fp,uint8_t * addr)91 void CodecHdiAdapterDecode::DumpOutputToFile(FILE *fp, uint8_t *addr)
92 {
93     size_t bufferSize = (stride_ * height_ * FRAME_SIZE_MULTI) / FRAME_SIZE_OPERATOR;
94     size_t ret = fwrite(addr, 1, bufferSize, fp);
95     if (ret != bufferSize) {
96         HDF_LOGE("%{public}s: Dump frame failed, ret: %{public}zu", __func__, ret);
97     }
98 }
99 
ReadOnePacket(FILE * fp,uint8_t * buf,uint32_t & filledCount)100 bool CodecHdiAdapterDecode::ReadOnePacket(FILE *fp, uint8_t *buf, uint32_t &filledCount)
101 {
102     filledCount = fread(buf, 1, inputBufferSize_, fp);
103     if (filledCount <= 0) {
104         return true;
105     }
106     return false;
107 }
108 
ReadOneFrameFromFile(FILE * fp,uint8_t * buf,uint32_t & filledCount)109 bool CodecHdiAdapterDecode::ReadOneFrameFromFile(FILE *fp, uint8_t *buf, uint32_t &filledCount)
110 {
111     int32_t readSize = 0;
112     // read start code first
113     size_t t = fread(buf, 1, START_CODE_SIZE_FRAME, fp);
114     if (t < START_CODE_SIZE_FRAME) {
115         return true;
116     }
117     uint8_t *temp = buf;
118     temp += START_CODE_SIZE_FRAME;
119     while (!feof(fp)) {
120         t = fread(temp, 1, 1, fp);
121         if (t != 1) {
122             continue;
123         }
124 
125         if (*temp == START_CODE) {
126             // check start code
127             if ((temp[START_CODE_OFFSET_ONE] == 0) && (temp[START_CODE_OFFSET_SEC] == 0) &&
128                 (temp[START_CODE_OFFSET_THIRD] == 0)) {
129                 fseek(fp, -START_CODE_SIZE_FRAME, SEEK_CUR);
130                 temp -= (START_CODE_SIZE_FRAME - 1);
131                 break;
132             } else if ((temp[START_CODE_OFFSET_ONE] == 0) && (temp[START_CODE_OFFSET_SEC] == 0)) {
133                 fseek(fp, -START_CODE_SIZE_SLICE, SEEK_CUR);
134                 temp -= (START_CODE_SIZE_SLICE - 1);
135                 break;
136             }
137         }
138         temp++;
139     }
140     readSize = (temp - buf);
141     filledCount = readSize;
142     totalSrcSize_ += readSize;
143     return (totalSrcSize_ >= srcFileSize_);
144 }
145 
Init(CommandOpt & opt)146 bool CodecHdiAdapterDecode::Init(CommandOpt &opt)
147 {
148     this->width_ = opt.width;
149     this->height_ = opt.height;
150     this->codecMime_ = opt.codec;
151     this->stride_ = AlignUp(opt.width);
152     this->useBufferHandle_ = opt.useBuffer;
153     HDF_LOGI("width[%{public}d], height[%{public}d],stride_[%{public}d],infile[%{public}s],outfile[%{public}s]",
154              width_, height_, stride_, opt.fileInput.c_str(), opt.fileOutput.c_str());
155 
156     struct stat fileStat = {0};
157     stat(opt.fileInput.c_str(), &fileStat);
158     srcFileSize_ = fileStat.st_size;
159     fpIn_ = fopen(opt.fileInput.c_str(), "rb");
160     fpOut_ = fopen(opt.fileOutput.c_str(), "wb+");
161     if ((fpIn_ == nullptr) || (fpOut_ == nullptr)) {
162         HDF_LOGE("%{public}s failed to open file %{public}s or %{public}s", __func__, opt.fileInput.c_str(),
163                  opt.fileOutput.c_str());
164         return false;
165     }
166 
167     omxMgr_ = GetCodecComponentManager();
168 
169     callback_ = CodecCallbackTypeGet(nullptr);
170     if ((omxMgr_ == nullptr) || (callback_ == nullptr)) {
171         HDF_LOGE("%{public}s omxMgr_ is null or callback_ is null", __func__);
172         return false;
173     }
174 
175     callback_->EventHandler = &CodecHdiAdapterDecode::OnEvent;
176     callback_->EmptyBufferDone = &CodecHdiAdapterDecode::OnEmptyBufferDone;
177     callback_->FillBufferDone = &CodecHdiAdapterDecode::OnFillBufferDone;
178     int32_t ret = HDF_SUCCESS;
179     if (codecMime_ == codecMime::AVC) {
180         ret = omxMgr_->CreateComponent(
181             &client_, &componentId_, const_cast<char *>(DECODER_AVC), (int64_t)this, callback_);
182     } else {
183         ret = omxMgr_->CreateComponent(
184             &client_, &componentId_, const_cast<char *>(DECODER_HEVC), (int64_t)this, callback_);
185     }
186 
187     if (ret != HDF_SUCCESS || client_ == nullptr) {
188         HDF_LOGE("%{public}s errNo[%{public}d] CreateComponent or client is null", __func__, ret);
189         return false;
190     }
191 
192     return true;
193 }
194 
ConfigMppPassthrough()195 int32_t CodecHdiAdapterDecode::ConfigMppPassthrough()
196 {
197     if (client_ == nullptr) {
198         HDF_LOGE("%{public}s error,client_ is null", __func__);
199         return HDF_FAILURE;
200     }
201     PassthroughParam param;
202     int32_t ret = memset_s(&param, sizeof(PassthroughParam), 0, sizeof(PassthroughParam));
203     if (ret != EOK) {
204         HDF_LOGE("%{public}s: memset_s param err [%{public}d].", __func__, ret);
205         return ret;
206     }
207     CodecType ct = VIDEO_DECODER;
208     param.key = KEY_CODEC_TYPE;
209     param.val = &ct;
210     param.size = sizeof(ct);
211     ret = client_->SetParameter(client_, OMX_IndexParamPassthrough,
212         reinterpret_cast<int8_t *>(&param), sizeof(param));
213     if (ret != HDF_SUCCESS) {
214         HDF_LOGE("%{public}s errNo[%{public}d] key is KEY_CODEC_TYPE", __func__, ret);
215         return ret;
216     }
217 
218     return ret;
219 }
220 
ConfigPortDefine()221 int32_t CodecHdiAdapterDecode::ConfigPortDefine()
222 {
223     if (client_ == nullptr) {
224         HDF_LOGE("%{public}s error,client_ is null", __func__);
225         return HDF_FAILURE;
226     }
227     // set width, height and color format on output port
228     OMX_PARAM_PORTDEFINITIONTYPE param;
229     InitParam(param);
230     param.nPortIndex = static_cast<uint32_t>(PortIndex::PORT_INDEX_OUTPUT);
231     auto ret = client_->GetParameter(client_, OMX_IndexParamPortDefinition,
232         reinterpret_cast<int8_t *>(&param), sizeof(param));
233     if (ret != HDF_SUCCESS) {
234         HDF_LOGE("%{public}s errNo[%{public}d] to GetParameter OMX_IndexParamPortDefinition", __func__, ret);
235         return ret;
236     }
237     HDF_LOGI("get format: eCompressionFormat = %{public}d, eColorFormat=%{public}d",
238              param.format.video.eCompressionFormat, param.format.video.eColorFormat);
239     param.format.video.nFrameWidth = width_;
240     param.format.video.nFrameHeight = height_;
241     param.format.video.nStride = stride_;
242     param.format.video.nSliceHeight = height_;
243     param.format.video.eColorFormat = AV_COLOR_FORMAT;  // YUV420SP
244     ret = client_->SetParameter(client_, OMX_IndexParamPortDefinition,
245         reinterpret_cast<int8_t *>(&param), sizeof(param));
246     if (ret != HDF_SUCCESS) {
247         HDF_LOGE("%{public}s errNo[%{public}d] to SetParameter OMX_IndexParamPortDefinition", __func__, ret);
248         return ret;
249     }
250     return ret;
251 }
252 
Configure()253 bool CodecHdiAdapterDecode::Configure()
254 {
255     if (client_ == nullptr) {
256         HDF_LOGE("%{public}s error,client_ is null", __func__);
257         return false;
258     }
259     if (ConfigMppPassthrough() != HDF_SUCCESS) {
260         HDF_LOGE("%{public}s error,ConfigMppPassthrough failed", __func__);
261         return false;
262     }
263     if (ConfigPortDefine() != HDF_SUCCESS) {
264         HDF_LOGE("%{public}s error,ConfigPortDefine failed", __func__);
265         return false;
266     }
267 
268     OMX_VIDEO_PARAM_PORTFORMATTYPE param;
269     InitParam(param);
270     param.nPortIndex = static_cast<uint32_t>(PortIndex::PORT_INDEX_INPUT);
271     auto ret = client_->GetParameter(client_, OMX_IndexParamVideoPortFormat,
272         reinterpret_cast<int8_t *>(&param), sizeof(param));
273     if (ret != HDF_SUCCESS) {
274         HDF_LOGE("%{public}s errNo[%{public}d] to GetParameter OMX_IndexParamVideoPortFormat", __func__, ret);
275         return false;
276     }
277     HDF_LOGI("set Format eCompressionFormat = %{public}d, eColorFormat=%{public}d",
278              param.eCompressionFormat, param.eColorFormat);
279     param.xFramerate = FRAME;  // 30fps,Q16 format
280     if (codecMime_ == codecMime::AVC) {
281         param.eCompressionFormat = OMX_VIDEO_CodingAVC;  // H264
282     } else {
283         param.eCompressionFormat = static_cast<OMX_VIDEO_CODINGTYPE>(CODEC_OMX_VIDEO_CodingHEVC);  // H265
284     }
285 
286     ret = client_->SetParameter(client_, OMX_IndexParamVideoPortFormat,
287         reinterpret_cast<int8_t *>(&param), sizeof(param));
288     if (ret != HDF_SUCCESS) {
289         HDF_LOGE("%{public}s errNo[%{public}d] to SetParameter OMX_IndexParamVideoPortFormat", __func__, ret);
290         return false;
291     }
292 
293     return true;
294 }
295 
UseBuffers()296 bool CodecHdiAdapterDecode::UseBuffers()
297 {
298     if (client_ == nullptr) {
299         HDF_LOGE("%{public}s error,client_ is null", __func__);
300         return HDF_FAILURE;
301     }
302     HDF_LOGI("...command to IDLE....");
303     auto ret = client_->SendCommand(client_, OMX_CommandStateSet, OMX_StateIdle, NULL, 0);
304     if (ret != HDF_SUCCESS) {
305         HDF_LOGE("%{public}s errNo[%{public}d] to SendCommand with StateSet:OMX_StateIdle", __func__, ret);
306         return false;
307     }
308 
309     ret = UseBufferOnPort(PortIndex::PORT_INDEX_INPUT);
310     if (ret != HDF_SUCCESS) {
311         HDF_LOGE("%{public}s errNo[%{public}d] UseBufferOnPort PortIndex::PORT_INDEX_INPUT", __func__, ret);
312         return false;
313     }
314 
315     ret = UseBufferOnPort(PortIndex::PORT_INDEX_OUTPUT);
316     if (ret != HDF_SUCCESS) {
317         HDF_LOGE("%{public}s errNo[%{public}d] UseBufferOnPort PortIndex::PORT_INDEX_OUTPUT", __func__, ret);
318         return false;
319     }
320 
321     HDF_LOGI("Wait for OMX_StateIdle status");
322     enum OMX_STATETYPE status;
323     ret = client_->GetState(client_, &status);
324     if (ret != HDF_SUCCESS) {
325         HDF_LOGE("%{public}s GetState ret [%{public}x]", __func__, ret);
326         return false;
327     }
328     if (status != OMX_StateIdle) {
329         HDF_LOGI("Wait for OMX_StateLoaded status");
330         this->WaitForStatusChanged();
331     } else {
332         HDF_LOGI("status is %{public}d", status);
333     }
334 
335     return true;
336 }
337 
UseBufferOnPort(PortIndex portIndex,int bufferCount,int bufferSize)338 int32_t CodecHdiAdapterDecode::UseBufferOnPort(PortIndex portIndex, int bufferCount, int bufferSize)
339 {
340     if (client_ == nullptr || bufferCount <= 0 || bufferSize <= 0) {
341         return HDF_ERR_INVALID_PARAM;
342     }
343     for (int i = 0; i < bufferCount; i++) {
344         std::shared_ptr<OmxCodecBuffer> omxBuffer = std::make_shared<OmxCodecBuffer>();
345         omxBuffer->size = sizeof(OmxCodecBuffer);
346         omxBuffer->version.s.nVersionMajor = 1;
347         omxBuffer->bufferType = CODEC_BUFFER_TYPE_AVSHARE_MEM_FD;
348         int fd = AshmemCreate(0, bufferSize);
349         shared_ptr<Ashmem> sharedMem = make_shared<Ashmem>(fd, bufferSize);
350         omxBuffer->bufferLen = FD_SIZE;
351         omxBuffer->buffer = reinterpret_cast<uint8_t *>(fd);
352         omxBuffer->allocLen = bufferSize;
353         omxBuffer->fenceFd = -1;
354         omxBuffer->pts = 0;
355         omxBuffer->flag = 0;
356 
357         if (portIndex == PortIndex::PORT_INDEX_INPUT) {
358             omxBuffer->type = READ_ONLY_TYPE;
359             sharedMem->MapReadAndWriteAshmem();
360         } else {
361             omxBuffer->type = READ_WRITE_TYPE;
362             sharedMem->MapReadOnlyAshmem();
363         }
364         auto ret = client_->AllocateBuffer(client_, static_cast<uint32_t>(portIndex), omxBuffer.get());
365         if (ret != HDF_SUCCESS) {
366             HDF_LOGE(
367                 "%{public}s errNo[%{public}d] to AllocateBuffer with portIndex[%{public}d]", __func__, ret, portIndex);
368             sharedMem->UnmapAshmem();
369             sharedMem->CloseAshmem();
370             sharedMem = nullptr;
371             return ret;
372         }
373         omxBuffer->bufferLen = 0;
374 
375         std::shared_ptr<BufferInfo> bufferInfo = std::make_shared<BufferInfo>();
376         bufferInfo->omxBuffer = omxBuffer;
377         bufferInfo->avSharedPtr = sharedMem;
378         bufferInfo->portIndex = portIndex;
379         omxBuffers_.emplace(std::make_pair(omxBuffer->bufferId, bufferInfo));
380     }
381 
382     return HDF_SUCCESS;
383 }
384 
UseBufferOnPort(PortIndex portIndex)385 int32_t CodecHdiAdapterDecode::UseBufferOnPort(PortIndex portIndex)
386 {
387     if (client_ == nullptr) {
388         HDF_LOGE("%{public}s error,client_ is null", __func__);
389         return HDF_FAILURE;
390     }
391     int32_t bufferSize = 0;
392     int32_t bufferCount = 0;
393     bool portEnable = false;
394 
395     OMX_PARAM_PORTDEFINITIONTYPE param;
396     InitParam(param);
397     param.nPortIndex = static_cast<OMX_U32>(portIndex);
398     auto ret = client_->GetParameter(client_, OMX_IndexParamPortDefinition,
399         reinterpret_cast<int8_t *>(&param), sizeof(param));
400     if (ret != HDF_SUCCESS) {
401         HDF_LOGE("%{public}s errNo[%{public}d] GetParameter with OMX_IndexParamPortDefinition:portIndex[%{public}d]",
402                  __func__, ret, portIndex);
403         return ret;
404     }
405 
406     bufferSize = param.nBufferSize;
407     if (portIndex == PortIndex::PORT_INDEX_INPUT) {
408         if (bufferSize == 0) {
409             bufferSize = width_ * height_;
410         }
411         inputBufferSize_ = bufferSize;
412     } else if (portIndex == PortIndex::PORT_INDEX_OUTPUT) {
413         bufferSize = width_ * height_ * FRAME_SIZE_OPERATOR;
414     }
415     bufferCount = param.nBufferCountActual;
416     portEnable = param.bEnabled;
417     HDF_LOGI("buffer index [%{public}d], buffer size [%{public}d], "
418              "buffer count [%{public}d], portEnable[%{public}d], ret [%{public}d]",
419              portIndex, bufferSize, bufferCount, portEnable, ret);
420 
421     ret = UseBufferOnPort(portIndex, bufferCount, bufferSize);
422     if (ret != HDF_SUCCESS) {
423         HDF_LOGE("%{public}s UseBufferOnPort ret[%{public}x]", __func__, ret);
424         return ret;
425     }
426 
427     return HDF_SUCCESS;
428 }
429 
FreeBuffers()430 void CodecHdiAdapterDecode::FreeBuffers()
431 {
432     if (client_ == nullptr) {
433         HDF_LOGE("%{public}s error,client_ is null", __func__);
434         return;
435     }
436     // command to loaded
437     (void)client_->SendCommand(client_, OMX_CommandStateSet, OMX_StateLoaded, nullptr, 0);
438 
439     // release all the buffers
440     auto iter = omxBuffers_.begin();
441     while (iter != omxBuffers_.end()) {
442         auto bufferInfo = iter->second;
443         iter = omxBuffers_.erase(iter);
444         (void)client_->FreeBuffer(client_, static_cast<uint32_t>(bufferInfo->portIndex), bufferInfo->omxBuffer.get());
445         bufferInfo = nullptr;
446     }
447 
448     unUsedInBuffers_.clear();
449     unUsedOutBuffers_.clear();
450 
451     enum OMX_STATETYPE status;
452     auto ret = client_->GetState(client_, &status);
453     if (ret != HDF_SUCCESS) {
454         HDF_LOGE("%{public}s GetState error [%{public}x]", __func__, ret);
455         return;
456     }
457     // wait loaded
458     if (status != OMX_StateLoaded) {
459         HDF_LOGI("Wait for OMX_StateLoaded status");
460         this->WaitForStatusChanged();
461     } else {
462         HDF_LOGI("status is %{public}d", status);
463     }
464 }
465 
Release()466 void CodecHdiAdapterDecode::Release()
467 {
468     omxMgr_->DestroyComponent(componentId_);
469     client_ = nullptr;
470     CodecComponentManagerRelease();
471 }
472 
GetFreeBufferId()473 int CodecHdiAdapterDecode::GetFreeBufferId()
474 {
475     int bufferID = -1;
476     unique_lock<mutex> ulk(lockInputBuffers_);
477     size_t nSize = this->unUsedInBuffers_.size();
478     if (nSize > 0) {
479         bufferID = unUsedInBuffers_.front();
480         unUsedInBuffers_.pop_front();
481     }
482     return bufferID;
483 }
484 
start()485 void CodecHdiAdapterDecode::start()
486 {
487     if (client_ == nullptr) {
488         HDF_LOGE("%{public}s error,client_ is null", __func__);
489         return;
490     }
491     auto ret = client_->SendCommand(client_, OMX_CommandStateSet, OMX_StateExecuting, NULL, 0);
492     if (ret != HDF_SUCCESS) {
493         HDF_LOGE("%{public}s errNo[%{public}d] to SendCommand with StateSet:OMX_StateIdle", __func__, ret);
494         return;
495     }
496 }
497 
Run()498 void CodecHdiAdapterDecode::Run()
499 {
500     CodecHdiAdapterDecode::start();
501     auto t1 = std::chrono::system_clock::now();
502     bool eosFlag = false;
503     while (!eosFlag) {
504         int bufferID = GetFreeBufferId();
505         if (this->exit_) {
506             break;
507         }
508         if (bufferID < 0) {
509             usleep(USLEEP_TIME);
510             continue;
511         }
512         auto iter = omxBuffers_.find(bufferID);
513         if (iter == omxBuffers_.end()) {
514             continue;
515         }
516         auto bufferInfo = iter->second;
517         void *sharedAddr = const_cast<void *>(bufferInfo->avSharedPtr->ReadFromAshmem(0, 0));
518         if (needSplit_ == 1) {
519             eosFlag = this->ReadOnePacket(fpIn_, reinterpret_cast<uint8_t *>(sharedAddr),
520                 bufferInfo->omxBuffer->filledLen);
521         } else {
522             eosFlag = this->ReadOneFrameFromFile(fpIn_, reinterpret_cast<uint8_t *>(sharedAddr),
523                 bufferInfo->omxBuffer->filledLen);
524         }
525         bufferInfo->omxBuffer->offset = 0;
526         if (eosFlag) {
527             bufferInfo->omxBuffer->flag = OMX_BUFFERFLAG_EOS;
528         }
529         auto ret = client_->EmptyThisBuffer(client_, bufferInfo->omxBuffer.get());
530         if (ret != HDF_SUCCESS) {
531             HDF_LOGE("%{public}s EmptyThisBuffer error", __func__);
532             return;
533         }
534     }
535     // wait
536     while (!this->exit_) {
537         usleep(USLEEP_TIME);
538     }
539     auto t2 = std::chrono::system_clock::now();
540     std::chrono::duration<double> diff = t2 - t1;
541     HDF_LOGI("cost %{public}f, count=%{public}d", diff.count(), count_);
542     // command to IDLE
543     (void)client_->SendCommand(client_, OMX_CommandStateSet, OMX_StateIdle, NULL, 0);
544     return;
545 }
546 
OnEvent(struct CodecCallbackType * self,OMX_EVENTTYPE event,struct EventInfo * info)547 int32_t CodecHdiAdapterDecode::OnEvent(struct CodecCallbackType *self, OMX_EVENTTYPE event, struct EventInfo *info)
548 {
549     if (event == OMX_EventCmdComplete) {
550         OMX_COMMANDTYPE cmd = static_cast<OMX_COMMANDTYPE>(info->data1);
551         if (OMX_CommandStateSet == cmd) {
552             HDF_LOGI("OMX_CommandStateSet reached, status is %{public}d", info->data2);
553             g_core->OnStatusChanged();
554         }
555     }
556 
557     return HDF_SUCCESS;
558 }
559 
OnEmptyBufferDone(struct CodecCallbackType * self,int64_t appData,const struct OmxCodecBuffer * buffer)560 int32_t CodecHdiAdapterDecode::OnEmptyBufferDone(
561     struct CodecCallbackType *self, int64_t appData, const struct OmxCodecBuffer *buffer)
562 {
563     return g_core->OnEmptyBufferDone(*buffer);
564 }
565 
OnFillBufferDone(struct CodecCallbackType * self,int64_t appData,const struct OmxCodecBuffer * buffer)566 int32_t CodecHdiAdapterDecode::OnFillBufferDone(
567     struct CodecCallbackType *self, int64_t appData, const struct OmxCodecBuffer *buffer)
568 {
569     return g_core->OnFillBufferDone(*buffer);
570 }
571 
OnEmptyBufferDone(const struct OmxCodecBuffer & buffer)572 int32_t CodecHdiAdapterDecode::OnEmptyBufferDone(const struct OmxCodecBuffer &buffer)
573 {
574     unique_lock<mutex> ulk(lockInputBuffers_);
575     unUsedInBuffers_.push_back(buffer.bufferId);
576     return HDF_SUCCESS;
577 }
578 
OnFillBufferDone(const struct OmxCodecBuffer & buffer)579 int32_t CodecHdiAdapterDecode::OnFillBufferDone(const struct OmxCodecBuffer &buffer)
580 {
581     if (client_ == nullptr) {
582         HDF_LOGE("%{public}s error,client_ is null", __func__);
583         return HDF_FAILURE;
584     }
585     if (exit_) {
586         return HDF_SUCCESS;
587     }
588 
589     auto iter = omxBuffers_.find(buffer.bufferId);
590     if ((iter == omxBuffers_.end()) || (iter->second == nullptr)) {
591         return HDF_SUCCESS;
592     }
593     count_++;
594     // read buffer
595     auto bufferInfo = iter->second;
596     if (bufferInfo->avSharedPtr != nullptr) {
597         const void *addr = bufferInfo->avSharedPtr->ReadFromAshmem(buffer.filledLen, buffer.offset);
598         DumpOutputToFile(fpOut_, reinterpret_cast<uint8_t *>(const_cast<void *>(addr)));
599     }
600 
601     (void)fflush(fpOut_);
602     if (buffer.flag == OMX_BUFFERFLAG_EOS) {
603         // end
604         exit_ = true;
605         HDF_LOGI("OnFillBufferDone the END coming");
606         return HDF_SUCCESS;
607     }
608     // call fillthisbuffer again
609     auto ret = client_->FillThisBuffer(client_, bufferInfo->omxBuffer.get());
610     if (ret != HDF_SUCCESS) {
611         HDF_LOGE("%{public}s FillThisBuffer error", __func__);
612         return HDF_SUCCESS;
613     }
614     return HDF_SUCCESS;
615 }
616 
main(int argc,char * argv[])617 int main(int argc, char *argv[])
618 {
619     CommandOpt opt;
620     CommandAdapterParse parse;
621     if (!parse.Parse(argc, argv, opt)) {
622         return HDF_FAILURE;
623     }
624     if (g_core == nullptr) {
625         g_core = new CodecHdiAdapterDecode();
626     }
627     // Init width, height, input file
628     if (!g_core->Init(opt)) {
629         delete g_core;
630         g_core = nullptr;
631         return HDF_FAILURE;
632     }
633 
634     if (!g_core->Configure()) {
635         delete g_core;
636         g_core = nullptr;
637         return HDF_FAILURE;
638     }
639 
640     if (!g_core->UseBuffers()) {
641         delete g_core;
642         g_core = nullptr;
643         return HDF_FAILURE;
644     }
645 
646     g_core->Run();
647     g_core->FreeBuffers();
648     g_core->Release();
649     delete g_core;
650     g_core = nullptr;
651 }
652