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