1/* 2 * Copyright (c) 2022-2023 Shenzhen Kaihong DID 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_decode.h" 17#include <hdf_base.h> 18#include <unistd.h> 19#include "codec_component_manager.h" 20#include "codec_omx_ext.h" 21 22using namespace std; 23using namespace OHOS; 24using namespace OHOS::HDI::Display::Buffer::V1_0; 25using namespace OHOS::HDI::Display::Composer::V1_0; 26namespace { 27constexpr uint32_t FD_SIZE = sizeof(int); 28constexpr uint32_t FRAME = 30 << 16; 29constexpr uint32_t DENOMINATOR = 2; 30constexpr uint32_t NUMERATOR = 3; 31constexpr uint32_t MAX_WAIT_COUNT = 3; 32} // namespace 33#define HDF_LOG_TAG codec_omx_hdi_dec 34IDisplayBuffer *CodecHdiDecode::buffer_ = nullptr; 35 36#define AV_COLOR_FORMAT OMX_COLOR_FormatYUV420SemiPlanar 37 38static CodecHdiDecode *g_core = nullptr; 39CodecHdiDecode::CodecHdiDecode() 40{ 41 client_ = nullptr; 42 callback_ = nullptr; 43 omxMgr_ = nullptr; 44 exit_ = false; 45 width_ = 0; 46 height_ = 0; 47 codecMime_ = CodecMime::AVC; 48 count_ = 0; 49 useBufferHandle_ = false; 50 componentId_ = 0; 51 reader_ = nullptr; 52 color_ = ColorFormat::YUV420SP; 53 omxColorFormat_ = OMX_COLOR_FormatYUV420SemiPlanar; 54} 55 56CodecHdiDecode::~CodecHdiDecode() 57{ 58 if (ioOut_.is_open()) { 59 ioOut_.close(); 60 } 61 if (ioIn_.is_open()) { 62 ioIn_.close(); 63 } 64} 65 66void CodecHdiDecode::WaitForStatusChanged() 67{ 68 unique_lock<mutex> autoLock(statusLock_); 69 statusCondition_.wait(autoLock); 70} 71 72void CodecHdiDecode::OnStatusChanged() 73{ 74 statusCondition_.notify_one(); 75} 76 77int CodecHdiDecode::GetYuvSize() 78{ 79 return width_ * height_ * NUMERATOR / DENOMINATOR; 80} 81 82bool CodecHdiDecode::Init(CommandOpt &opt) 83{ 84 this->width_ = opt.width; 85 this->height_ = opt.height; 86 this->codecMime_ = opt.codec; 87 this->stride_ = AlignUp(opt.width); 88 this->useBufferHandle_ = opt.useBuffer; 89 color_ = opt.colorForamt; 90 if (color_ == ColorFormat::RGBA8888) { 91 omxColorFormat_ = static_cast<OMX_COLOR_FORMATTYPE>(CODEC_COLOR_FORMAT_RGBA8888); 92 } else if (color_ == ColorFormat::BGRA8888) { 93 omxColorFormat_ = OMX_COLOR_Format32bitBGRA8888; 94 } 95 HDF_LOGI("width[%{public}d], height[%{public}d],stride_[%{public}d],infile[%{public}s],outfile[%{public}s]", width_, 96 height_, stride_, opt.fileInput.c_str(), opt.fileOutput.c_str()); 97 98 // gralloc init 99 buffer_ = IDisplayBuffer::Get(); 100 reader_ = CodecPacketReader::GetPacketReader(opt.codec); 101 ioIn_.open(opt.fileInput, std::ios_base::binary); 102 ioOut_.open(opt.fileOutput, std::ios_base::binary | std::ios_base::trunc); 103 if (!ioOut_.is_open() || !ioIn_.is_open()) { 104 HDF_LOGE("%{public}s failed to open file %{public}s or %{public}s", __func__, opt.fileInput.c_str(), 105 opt.fileOutput.c_str()); 106 return false; 107 } 108 109 omxMgr_ = GetCodecComponentManager(); 110 111 callback_ = CodecCallbackTypeGet(nullptr); 112 if ((omxMgr_ == nullptr) || (callback_ == nullptr)) { 113 HDF_LOGE("%{public}s omxMgr_ is null or callback_ is null", __func__); 114 return false; 115 } 116 117 callback_->EventHandler = &CodecHdiDecode::OnEvent; 118 callback_->EmptyBufferDone = &CodecHdiDecode::OnEmptyBufferDone; 119 callback_->FillBufferDone = &CodecHdiDecode::OnFillBufferDone; 120 int32_t err = GetComponent(); 121 if (err != HDF_SUCCESS) { 122 HDF_LOGE("%{public}s failed to CreateComponent", __func__); 123 return false; 124 } 125 126 struct CompVerInfo verInfo; 127 err = memset_s(&verInfo, sizeof(verInfo), 0, sizeof(verInfo)); 128 if (err != EOK) { 129 HDF_LOGE("%{public}s: memset_s verInfo err [%{public}d].", __func__, err); 130 return false; 131 } 132 err = client_->GetComponentVersion(client_, &verInfo); 133 if (err != HDF_SUCCESS) { 134 HDF_LOGE("%{public}s failed to CreateComponent", __func__); 135 return false; 136 } 137 138 return true; 139} 140 141int32_t CodecHdiDecode::ConfigPortDefine() 142{ 143 // set width and height on input port 144 OMX_PARAM_PORTDEFINITIONTYPE param; 145 InitParam(param); 146 param.nPortIndex = static_cast<uint32_t>(PortIndex::PORT_INDEX_INPUT); 147 auto err = 148 client_->GetParameter(client_, OMX_IndexParamPortDefinition, reinterpret_cast<int8_t *>(¶m), sizeof(param)); 149 if (err != HDF_SUCCESS) { 150 HDF_LOGE("%{public}s failed PortIndex::PORT_INDEX_INPUT, index is OMX_IndexParamPortDefinition", __func__); 151 return err; 152 } 153 HDF_LOGI("PortIndex::PORT_INDEX_INPUT: eCompressionFormat = %{public}d, eColorFormat = %{public}d ", 154 param.format.video.eCompressionFormat, param.format.video.eColorFormat); 155 param.format.video.nFrameWidth = width_; 156 param.format.video.nFrameHeight = height_; 157 param.format.video.nStride = stride_; 158 param.format.video.nSliceHeight = height_; 159 err = 160 client_->SetParameter(client_, OMX_IndexParamPortDefinition, reinterpret_cast<int8_t *>(¶m), sizeof(param)); 161 if (err != HDF_SUCCESS) { 162 HDF_LOGE("%{public}s failed with PortIndex::PORT_INDEX_INPUT, index is OMX_IndexParamPortDefinition", __func__); 163 return err; 164 } 165 166 // set width, height and color format on output port 167 InitParam(param); 168 param.nPortIndex = static_cast<uint32_t>(PortIndex::PORT_INDEX_OUTPUT); 169 err = 170 client_->GetParameter(client_, OMX_IndexParamPortDefinition, reinterpret_cast<int8_t *>(¶m), sizeof(param)); 171 if (err != HDF_SUCCESS) { 172 HDF_LOGE("%{public}s failed with PortIndex::PORT_INDEX_OUTPUT, index is OMX_IndexParamPortDefinition", 173 __func__); 174 return err; 175 } 176 HDF_LOGI("PortIndex::PORT_INDEX_OUTPUT eCompressionFormat = %{public}d, eColorFormat=%{public}d", 177 param.format.video.eCompressionFormat, param.format.video.eColorFormat); 178 param.format.video.nFrameWidth = width_; 179 param.format.video.nFrameHeight = height_; 180 param.format.video.nStride = stride_; 181 param.format.video.nSliceHeight = height_; 182 param.format.video.eColorFormat = omxColorFormat_; 183 err = 184 client_->SetParameter(client_, OMX_IndexParamPortDefinition, reinterpret_cast<int8_t *>(¶m), sizeof(param)); 185 if (err != HDF_SUCCESS) { 186 HDF_LOGE("%{public}s failed with PortIndex::PORT_INDEX_OUTPUT, index is OMX_IndexParamPortDefinition", 187 __func__); 188 return err; 189 } 190 return err; 191} 192bool CodecHdiDecode::Configure() 193{ 194 if (ConfigPortDefine() != HDF_SUCCESS) { 195 return false; 196 } 197 198 OMX_VIDEO_PARAM_PORTFORMATTYPE param; 199 InitParam(param); 200 param.nPortIndex = static_cast<uint32_t>(PortIndex::PORT_INDEX_INPUT); 201 auto err = client_->GetParameter(client_, OMX_IndexParamVideoPortFormat, reinterpret_cast<int8_t *>(¶m), 202 sizeof(param)); 203 if (err != HDF_SUCCESS) { 204 HDF_LOGE("%{public}s failed with PortIndex::PORT_INDEX_INPUT", __func__); 205 return false; 206 } 207 HDF_LOGI("set Format PortIndex::PORT_INDEX_INPUT eCompressionFormat = %{public}d, eColorFormat=%{public}d", 208 param.eCompressionFormat, param.eColorFormat); 209 param.xFramerate = FRAME; // 30fps,Q16 format 210 switch (codecMime_) { 211 case CodecMime::AVC: 212 param.eCompressionFormat = OMX_VIDEO_CodingAVC; // H264 213 break; 214 case CodecMime::HEVC: 215 param.eCompressionFormat = (OMX_VIDEO_CODINGTYPE)CODEC_OMX_VIDEO_CodingHEVC; // H265 216 break; 217 case CodecMime::MPEG4: 218 param.eCompressionFormat = OMX_VIDEO_CodingMPEG4; // H264 219 break; 220 case CodecMime::VP9: 221 param.eCompressionFormat = (OMX_VIDEO_CODINGTYPE)CODEC_OMX_VIDEO_CodingVP9; // H264 222 break; 223 default: 224 break; 225 } 226 227 err = client_->SetParameter(client_, OMX_IndexParamVideoPortFormat, reinterpret_cast<int8_t *>(¶m), 228 sizeof(param)); 229 if (err != HDF_SUCCESS) { 230 HDF_LOGE("%{public}s failed with PortIndex::PORT_INDEX_INPUT", __func__); 231 return false; 232 } 233 234 err = CheckAndUseBufferHandle(); 235 if (err != HDF_SUCCESS) { 236 HDF_LOGE("%{public}s failed with CheckAndUseBufferHandle", __func__); 237 return false; 238 } 239 return true; 240} 241 242int32_t CodecHdiDecode::CheckAndUseBufferHandle() 243{ 244 if (!useBufferHandle_) { 245 return HDF_SUCCESS; 246 } 247 SupportBufferType param; 248 InitParamInOhos(param); 249 param.portIndex = static_cast<uint32_t>(PortIndex::PORT_INDEX_INPUT); 250 251 auto err = client_->GetParameter(client_, OMX_IndexParamSupportBufferType, reinterpret_cast<int8_t *>(¶m), 252 sizeof(param)); 253 HDF_LOGI( 254 "OMX_GetParameter:OMX_IndexParamSupportBufferType:kPortIndexInput, err [%{public}x], bufferTypes[%{public}d]", 255 err, param.bufferTypes); 256 if (err != HDF_SUCCESS) { 257 return err; 258 } 259 InitParamInOhos(param); 260 param.portIndex = static_cast<uint32_t>(PortIndex::PORT_INDEX_OUTPUT); 261 err = client_->GetParameter(client_, OMX_IndexParamSupportBufferType, reinterpret_cast<int8_t *>(¶m), 262 sizeof(param)); 263 HDF_LOGI( 264 "OMX_GetParameter:OMX_IndexParamSupportBufferType:kPortIndexOutput, err [%{public}x], bufferTypes[%{public}d]", 265 err, param.bufferTypes); 266 if (err != HDF_SUCCESS) { 267 return err; 268 } 269 GetBufferHandleUsageParams usage; 270 InitParamInOhos(usage); 271 usage.portIndex = static_cast<uint32_t>(PortIndex::PORT_INDEX_OUTPUT); 272 err = client_->GetParameter(client_, OMX_IndexParamGetBufferHandleUsage, reinterpret_cast<int8_t *>(&usage), 273 sizeof(usage)); 274 HDF_LOGI("OMX_GetParameter:GetBufferHandleUsage:kPortIndexOutput, err [%{public}x], usage[%{public}" PRIu64 "]", 275 err, usage.usage); 276 if (err != HDF_SUCCESS) { 277 return err; 278 } 279 UseBufferType type; 280 InitParamInOhos(type); 281 type.portIndex = static_cast<uint32_t>(PortIndex::PORT_INDEX_OUTPUT); 282 type.bufferType = CODEC_BUFFER_TYPE_HANDLE; 283 err = client_->SetParameter(client_, OMX_IndexParamUseBufferType, reinterpret_cast<int8_t *>(&type), sizeof(type)); 284 HDF_LOGI("OMX_SetParameter:OMX_IndexParamUseBufferType:kPortIndexOutput, err [%{public}x]", err); 285 return err; 286} 287 288bool CodecHdiDecode::UseBuffers() 289{ 290 HDF_LOGI("...command to IDLE...."); 291 auto err = client_->SendCommand(client_, OMX_CommandStateSet, OMX_StateIdle, NULL, 0); 292 if (err != HDF_SUCCESS) { 293 HDF_LOGE("%{public}s failed to SendCommand with OMX_CommandStateSet:OMX_StateIdle", __func__); 294 return false; 295 } 296 297 err = UseBufferOnPort(PortIndex::PORT_INDEX_INPUT); 298 if (err != HDF_SUCCESS) { 299 HDF_LOGE("%{public}s UseBufferOnPort PortIndex::PORT_INDEX_INPUT error", __func__); 300 return false; 301 } 302 303 err = UseBufferOnPort(PortIndex::PORT_INDEX_OUTPUT); 304 if (err != HDF_SUCCESS) { 305 HDF_LOGE("%{public}s UseBufferOnPort PortIndex::PORT_INDEX_OUTPUT error", __func__); 306 return false; 307 } 308 309 HDF_LOGI("Wait for OMX_StateIdle status"); 310 OMX_STATETYPE status; 311 err = client_->GetState(client_, &status); 312 if (err != HDF_SUCCESS) { 313 HDF_LOGE("%{public}s GetState err [%{public}x]", __func__, err); 314 return false; 315 } 316 if (status != OMX_StateIdle) { 317 HDF_LOGI("Wait for OMX_StateLoaded status"); 318 this->WaitForStatusChanged(); 319 } else { 320 HDF_LOGI(" status is %{public}d", status); 321 } 322 323 return true; 324} 325 326int32_t CodecHdiDecode::UseBufferOnPort(PortIndex portIndex, int bufferCount, int bufferSize) 327{ 328 if (bufferCount <= 0 || bufferSize <= 0) { 329 return HDF_ERR_INVALID_PARAM; 330 } 331 for (int i = 0; i < bufferCount; i++) { 332 std::shared_ptr<OmxCodecBuffer> omxBuffer = std::make_shared<OmxCodecBuffer>(); 333 omxBuffer->size = sizeof(OmxCodecBuffer); 334 omxBuffer->version.s.nVersionMajor = 1; 335 omxBuffer->bufferType = CODEC_BUFFER_TYPE_AVSHARE_MEM_FD; 336 int fd = AshmemCreate(0, bufferSize); 337 shared_ptr<Ashmem> sharedMem = make_shared<Ashmem>(fd, bufferSize); 338 omxBuffer->bufferLen = FD_SIZE; 339 omxBuffer->buffer = reinterpret_cast<uint8_t *>(fd); 340 omxBuffer->allocLen = bufferSize; 341 omxBuffer->fenceFd = -1; 342 omxBuffer->pts = 0; 343 omxBuffer->flag = 0; 344 345 if (portIndex == PortIndex::PORT_INDEX_INPUT) { 346 omxBuffer->type = READ_ONLY_TYPE; 347 sharedMem->MapReadAndWriteAshmem(); 348 } else { 349 omxBuffer->type = READ_WRITE_TYPE; 350 sharedMem->MapReadOnlyAshmem(); 351 } 352 auto err = client_->UseBuffer(client_, static_cast<uint32_t>(portIndex), omxBuffer.get()); 353 if (err != HDF_SUCCESS) { 354 HDF_LOGE("%{public}s failed to UseBuffer with portIndex[%{public}d]", __func__, portIndex); 355 sharedMem->UnmapAshmem(); 356 sharedMem->CloseAshmem(); 357 sharedMem = nullptr; 358 return err; 359 } 360 omxBuffer->bufferLen = 0; 361 HDF_LOGI("UseBuffer returned bufferID [%{public}d]", omxBuffer->bufferId); 362 363 std::shared_ptr<BufferInfo> bufferInfo = std::make_shared<BufferInfo>(); 364 bufferInfo->omxBuffer = omxBuffer; 365 bufferInfo->avSharedPtr = sharedMem; 366 bufferInfo->portIndex = portIndex; 367 omxBuffers_.emplace(std::make_pair(omxBuffer->bufferId, bufferInfo)); 368 if (portIndex == PortIndex::PORT_INDEX_INPUT) { 369 unUsedInBuffers_.push_back(omxBuffer->bufferId); 370 } else { 371 unUsedOutBuffers_.push_back(omxBuffer->bufferId); 372 } 373 } 374 375 return HDF_SUCCESS; 376} 377 378int32_t CodecHdiDecode::UseBufferOnPort(PortIndex portIndex) 379{ 380 HDF_LOGI("%{public}s enter, portIndex = %{public}d", __func__, portIndex); 381 382 OMX_PARAM_PORTDEFINITIONTYPE param; 383 InitParam(param); 384 param.nPortIndex = static_cast<OMX_U32>(portIndex); 385 auto err = 386 client_->GetParameter(client_, OMX_IndexParamPortDefinition, reinterpret_cast<int8_t *>(¶m), sizeof(param)); 387 if (err != HDF_SUCCESS) { 388 HDF_LOGE("%{public}s failed to GetParameter with OMX_IndexParamPortDefinition : portIndex[%{public}d]", 389 __func__, portIndex); 390 return err; 391 } 392 393 int bufferSize = param.nBufferSize; 394 int bufferCount = param.nBufferCountActual; 395 bool portEnable = param.bEnabled; 396 HDF_LOGI("buffer index [%{public}d], buffer size [%{public}d], " 397 "buffer count [%{public}d], portEnable[%{public}d], err [%{public}d]", 398 portIndex, bufferSize, bufferCount, portEnable, err); 399 400 { 401 OMX_PARAM_BUFFERSUPPLIERTYPE param; 402 InitParam(param); 403 param.nPortIndex = static_cast<uint32_t>(portIndex); 404 err = client_->GetParameter(client_, OMX_IndexParamCompBufferSupplier, reinterpret_cast<int8_t *>(¶m), 405 sizeof(param)); 406 HDF_LOGI("param.eBufferSupplier[%{public}d] err [%{public}d]", param.eBufferSupplier, err); 407 } 408 if (useBufferHandle_ && portIndex == PortIndex::PORT_INDEX_OUTPUT) { 409 err = UseBufferHandle(bufferCount, bufferSize); 410 } else { 411 err = UseBufferOnPort(portIndex, bufferCount, bufferSize); 412 } 413 414 if (err != HDF_SUCCESS) { 415 HDF_LOGE("%{public}s UseBufferOnPort err[%{public}x]", __func__, err); 416 return err; 417 } 418 // set port enable 419 if (!portEnable) { 420 err = client_->SendCommand(client_, OMX_CommandPortEnable, static_cast<uint32_t>(portIndex), NULL, 0); 421 if (err != HDF_SUCCESS) { 422 HDF_LOGE("%{public}s SendCommand OMX_CommandPortEnable::PortIndex::PORT_INDEX_INPUT error", __func__); 423 return err; 424 } 425 } 426 return HDF_SUCCESS; 427} 428 429int32_t CodecHdiDecode::UseBufferHandle(int bufferCount, int bufferSize) 430{ 431 if (bufferCount <= 0 || bufferSize <= 0 || buffer_ == nullptr) { 432 return HDF_ERR_INVALID_PARAM; 433 } 434 PixelFormat pixForamt = PIXEL_FMT_YCBCR_420_SP; 435 if (color_ == ColorFormat::RGBA8888) { 436 pixForamt = PIXEL_FMT_RGBA_8888; 437 } else if (color_ == ColorFormat::BGRA8888) { 438 pixForamt = PIXEL_FMT_BGRA_8888; 439 } 440 AllocInfo alloc = {.width = this->width_, 441 .height = this->height_, 442 .usage = HBM_USE_CPU_READ | HBM_USE_CPU_WRITE | HBM_USE_MEM_DMA, 443 .format = pixForamt}; 444 445 for (int i = 0; i < bufferCount; i++) { 446 int32_t ret = HDF_SUCCESS; 447 std::shared_ptr<OmxCodecBuffer> omxBuffer = std::make_shared<OmxCodecBuffer>(); 448 omxBuffer->size = sizeof(OmxCodecBuffer); 449 omxBuffer->version.s.nVersionMajor = 1; 450 omxBuffer->bufferType = CODEC_BUFFER_TYPE_HANDLE; 451 BufferHandle *bufferHandle = nullptr; 452 ret = buffer_->AllocMem(alloc, bufferHandle); 453 HDF_LOGI("%{public}s AlloceMem ret val err[%{public}d]", __func__, ret); 454 if (DISPLAY_SUCCESS != ret) { 455 HDF_LOGE("%{public}s AllocMem error", __func__); 456 return ret; 457 } 458 size_t handleSize = 459 sizeof(BufferHandle) + (sizeof(int32_t) * (bufferHandle->reserveFds + bufferHandle->reserveInts)); 460 omxBuffer->bufferLen = handleSize; 461 omxBuffer->buffer = reinterpret_cast<uint8_t *>(bufferHandle); 462 omxBuffer->allocLen = bufferSize; 463 omxBuffer->fenceFd = -1; // check use -1 first with no window 464 omxBuffer->pts = 0; 465 omxBuffer->flag = 0; 466 auto err = client_->UseBuffer(client_, static_cast<uint32_t>(PortIndex::PORT_INDEX_OUTPUT), omxBuffer.get()); 467 if (err != HDF_SUCCESS) { 468 HDF_LOGE("%{public}s failed to UseBuffer with output port]", __func__); 469 return err; 470 } 471 omxBuffer->bufferLen = 0; 472 HDF_LOGI("UseBuffer returned bufferID [%{public}d]", omxBuffer->bufferId); 473 474 std::shared_ptr<BufferInfo> bufferInfo = std::make_shared<BufferInfo>(); 475 bufferInfo->omxBuffer = omxBuffer; 476 bufferInfo->setBufferHandle(bufferHandle); 477 bufferInfo->portIndex = PortIndex::PORT_INDEX_OUTPUT; 478 omxBuffers_.emplace(std::make_pair(omxBuffer->bufferId, bufferInfo)); 479 unUsedOutBuffers_.push_back(omxBuffer->bufferId); 480 } 481 return HDF_SUCCESS; 482} 483 484void CodecHdiDecode::FreeBuffers() 485{ 486 // command to loaded 487 (void)client_->SendCommand(client_, OMX_CommandStateSet, OMX_StateLoaded, nullptr, 0); 488 489 // release all the buffers 490 auto iter = omxBuffers_.begin(); 491 while (iter != omxBuffers_.end()) { 492 auto bufferInfo = iter->second; 493 iter = omxBuffers_.erase(iter); 494 (void)client_->FreeBuffer(client_, static_cast<uint32_t>(bufferInfo->portIndex), bufferInfo->omxBuffer.get()); 495 bufferInfo = nullptr; 496 } 497 498 unUsedInBuffers_.clear(); 499 unUsedOutBuffers_.clear(); 500 501 // wait loaded 502 OMX_STATETYPE status = OMX_StateLoaded; 503 int32_t tryCount = MAX_WAIT_COUNT; 504 do { 505 int32_t err = client_->GetState(client_, &status); 506 if (err != HDF_SUCCESS) { 507 HDF_LOGE("%s GetState error [%{public}x]", __func__, err); 508 break; 509 } 510 if (status != OMX_StateLoaded) { 511 HDF_LOGI("Wait for OMX_StateLoaded status"); 512 this->WaitForStatusChanged(); 513 } 514 tryCount--; 515 } while ((status != OMX_StateLoaded) && (tryCount > 0)); 516} 517 518void CodecHdiDecode::Release() 519{ 520 omxMgr_->DestroyComponent(componentId_); 521 CodecComponentTypeRelease(client_); 522 client_ = nullptr; 523 CodecComponentManagerRelease(); 524} 525 526bool CodecHdiDecode::FillAllTheBuffer() 527{ 528 for (auto bufferId : unUsedOutBuffers_) { 529 HDF_LOGI("fill bufferid [%{public}d]", bufferId); 530 auto iter = omxBuffers_.find(bufferId); 531 if (iter != omxBuffers_.end()) { 532 auto bufferInfo = iter->second; 533 auto buffer = bufferInfo->omxBuffer.get(); 534 if (bufferInfo->bufferHandle != nullptr) { 535 buffer->buffer = reinterpret_cast<uint8_t *>(bufferInfo->bufferHandle); 536 buffer->bufferLen = sizeof(BufferHandle) + sizeof(int32_t) * (bufferInfo->bufferHandle->reserveFds + 537 bufferInfo->bufferHandle->reserveInts); 538 } 539 540 auto err = client_->FillThisBuffer(client_, buffer); 541 if (err != HDF_SUCCESS) { 542 HDF_LOGE("%{public}s FillThisBuffer error", __func__); 543 return false; 544 } 545 } 546 } 547 return true; 548} 549 550int CodecHdiDecode::GetFreeBufferId() 551{ 552 int bufferID = -1; 553 unique_lock<mutex> ulk(lockInputBuffers_); 554 size_t nSize = this->unUsedInBuffers_.size(); 555 if (nSize > 0) { 556 bufferID = unUsedInBuffers_.front(); 557 unUsedInBuffers_.pop_front(); 558 } 559 return bufferID; 560} 561 562int32_t CodecHdiDecode::GetComponent() 563{ 564 int32_t count = omxMgr_->GetComponentNum(); 565 if (count <= 0) { 566 HDF_LOGE("%{public}s: GetComponentNum ret %{public}d", __func__, count); 567 return HDF_FAILURE; 568 } 569 auto caps = std::make_unique<CodecCompCapability[]>(count); 570 auto err = omxMgr_->GetComponentCapabilityList(caps.get(), count); 571 if (err != HDF_SUCCESS) { 572 HDF_LOGE("%{public}s: GetComponentCapabilityList ret %{public}d", __func__, err); 573 return err; 574 } 575 std::string compName(""); 576 for (int32_t i = 0; i < count; i++) { 577 if (caps[i].type != VIDEO_DECODER) { 578 continue; 579 } 580 if (((caps[i].role == MEDIA_ROLETYPE_VIDEO_AVC) && (codecMime_ == CodecMime::AVC)) || 581 ((caps[i].role == MEDIA_ROLETYPE_VIDEO_HEVC) && (codecMime_ == CodecMime::HEVC)) || 582 ((caps[i].role == MEDIA_ROLETYPE_VIDEO_VP9) && (codecMime_ == CodecMime::VP9)) || 583 ((caps[i].role == MEDIA_ROLETYPE_VIDEO_MPEG4) && (codecMime_ == CodecMime::MPEG4))) { 584 compName = caps[i].compName; 585 break; 586 } 587 } 588 if (compName.empty()) { 589 HDF_LOGE("%{public}s: role is unexpected ", __func__); 590 return HDF_FAILURE; 591 } 592 return omxMgr_->CreateComponent(&client_, &componentId_, compName.data(), reinterpret_cast<int64_t>(this), 593 callback_); 594} 595 596void CodecHdiDecode::Run() 597{ 598 HDF_LOGI("...command to OMX_StateExecuting...."); 599 auto err = client_->SendCommand(client_, OMX_CommandStateSet, OMX_StateExecuting, NULL, 0); 600 if (err != HDF_SUCCESS) { 601 HDF_LOGE("%{public}s failed to SendCommand with OMX_CommandStateSet:OMX_StateIdle", __func__); 602 return; 603 } 604 605 if (!FillAllTheBuffer()) { 606 HDF_LOGE("%{public}s FillAllTheBuffer error", __func__); 607 return; 608 } 609 610 auto t1 = std::chrono::system_clock::now(); 611 bool eosFlag = false; 612 while (!eosFlag) { 613 HDF_LOGI(" inputput run"); 614 int bufferID = GetFreeBufferId(); 615 if (this->exit_) { 616 break; 617 } 618 if (bufferID < 0) { 619 usleep(10000); // 10000: sleep time 10ms 620 continue; 621 } 622 auto iter = omxBuffers_.find(bufferID); 623 if (iter == omxBuffers_.end()) { 624 continue; 625 } 626 auto bufferInfo = iter->second; 627 const char *sharedAddr = static_cast<const char *>(bufferInfo->avSharedPtr->ReadFromAshmem(0, 0)); 628 eosFlag = reader_->ReadOnePacket(ioIn_, const_cast<char *>(sharedAddr), bufferInfo->omxBuffer->filledLen); 629 bufferInfo->omxBuffer->offset = 0; 630 if (eosFlag) { 631 bufferInfo->omxBuffer->flag = OMX_BUFFERFLAG_EOS; 632 } 633 err = client_->EmptyThisBuffer(client_, bufferInfo->omxBuffer.get()); 634 if (err != HDF_SUCCESS) { 635 HDF_LOGE("%{public}s EmptyThisBuffer error", __func__); 636 return; 637 } 638 } 639 // wait 640 while (!this->exit_) { 641 usleep(10000); // 10000: sleep time 10ms 642 } 643 auto t2 = std::chrono::system_clock::now(); 644 std::chrono::duration<double> diff = t2 - t1; 645 HDF_LOGI("decoder costtime %{public}f, count=%{public}d", diff.count(), count_); 646 // command to IDLE 647 (void)client_->SendCommand(client_, OMX_CommandStateSet, OMX_StateIdle, NULL, 0); 648 return; 649} 650int32_t CodecHdiDecode::OnEvent(struct CodecCallbackType *self, OMX_EVENTTYPE event, struct EventInfo *info) 651{ 652 HDF_LOGI("%{public}s: appData[%{public}" PRId64 "] eEvent [%{public}d], nData1[%{public}d]", __func__, 653 info->appData, event, info->data1); 654 if (event == OMX_EventCmdComplete) { 655 OMX_COMMANDTYPE cmd = static_cast<OMX_COMMANDTYPE>(info->data1); 656 if (OMX_CommandStateSet == cmd) { 657 HDF_LOGI("OMX_CommandStateSet reached, status is %{public}d", info->data2); 658 g_core->OnStatusChanged(); 659 } 660 } 661 return HDF_SUCCESS; 662} 663 664int32_t CodecHdiDecode::OnEmptyBufferDone(struct CodecCallbackType *self, int64_t appData, 665 const struct OmxCodecBuffer *buffer) 666{ 667 HDF_LOGI("onEmptyBufferDone: pBuffer.bufferID [%{public}d]", buffer->bufferId); 668 return g_core->OnEmptyBufferDone(*buffer); 669} 670 671int32_t CodecHdiDecode::OnFillBufferDone(struct CodecCallbackType *self, int64_t appData, 672 const struct OmxCodecBuffer *buffer) 673{ 674 HDF_LOGI("onFillBufferDone: pBuffer.bufferID [%{public}d]", buffer->bufferId); 675 return g_core->OnFillBufferDone(*buffer); 676} 677 678int32_t CodecHdiDecode::OnEmptyBufferDone(const struct OmxCodecBuffer &buffer) 679{ 680 unique_lock<mutex> ulk(lockInputBuffers_); 681 unUsedInBuffers_.push_back(buffer.bufferId); 682 return HDF_SUCCESS; 683} 684 685int32_t CodecHdiDecode::OnFillBufferDone(const struct OmxCodecBuffer &buffer) 686{ 687 if (exit_) { 688 return HDF_SUCCESS; 689 } 690 691 auto iter = omxBuffers_.find(buffer.bufferId); 692 if ((iter == omxBuffers_.end()) || (iter->second == nullptr)) { 693 return HDF_SUCCESS; 694 } 695 count_++; 696 // read buffer 697 auto bufferInfo = iter->second; 698 if (bufferInfo->avSharedPtr != nullptr) { 699 void *addr = const_cast<void *>(bufferInfo->avSharedPtr->ReadFromAshmem(buffer.filledLen, buffer.offset)); 700 ioOut_.write(static_cast<char *>(addr), buffer.filledLen); 701 } else if (bufferInfo->bufferHandle != nullptr && buffer_ != nullptr) { 702 buffer_->Mmap(*bufferInfo->bufferHandle); 703 ioOut_.write(static_cast<char *>(bufferInfo->bufferHandle->virAddr), bufferInfo->bufferHandle->size); 704 buffer_->Unmap(*bufferInfo->bufferHandle); 705 } 706 707 ioOut_.flush(); 708 if (buffer.flag == OMX_BUFFERFLAG_EOS) { 709 // end 710 exit_ = true; 711 HDF_LOGI("OnFillBufferDone the END coming"); 712 return HDF_SUCCESS; 713 } 714 // call fillthisbuffer again 715 auto err = client_->FillThisBuffer(client_, bufferInfo->omxBuffer.get()); 716 if (err != HDF_SUCCESS) { 717 HDF_LOGE("%{public}s FillThisBuffer error", __func__); 718 return HDF_SUCCESS; 719 } 720 return HDF_SUCCESS; 721} 722 723int main(int argc, char *argv[]) 724{ 725 CommandOpt opt; 726 CommandParse parse; 727 if (!parse.Parse(argc, argv, opt)) { 728 return HDF_FAILURE; 729 } 730 if (g_core == nullptr) { 731 g_core = new CodecHdiDecode(); 732 } 733 // Init width, height, input file 734 if (!g_core->Init(opt)) { 735 delete g_core; 736 g_core = nullptr; 737 return HDF_FAILURE; 738 } 739 740 if (!g_core->Configure()) { 741 delete g_core; 742 g_core = nullptr; 743 return HDF_FAILURE; 744 } 745 746 if (!g_core->UseBuffers()) { 747 delete g_core; 748 g_core = nullptr; 749 return HDF_FAILURE; 750 } 751 752 g_core->Run(); 753 g_core->FreeBuffers(); 754 g_core->Release(); 755 delete g_core; 756 g_core = nullptr; 757}