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