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(¶m, 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 *)¶m, 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(¶m, 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 *)¶m, 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(¶m, 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 *)¶m, 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 *)¶m, 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 *)¶m, 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 *)¶m, 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 *)¶m, 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 *)¶m, 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