1094332d3Sopenharmony_ci/* 2094332d3Sopenharmony_ci * Copyright 2023 Shenzhen Kaihong DID Co., Ltd. 3094332d3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4094332d3Sopenharmony_ci * you may not use this file except in compliance with the License. 5094332d3Sopenharmony_ci * You may obtain a copy of the License at 6094332d3Sopenharmony_ci * 7094332d3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8094332d3Sopenharmony_ci * 9094332d3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10094332d3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11094332d3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12094332d3Sopenharmony_ci * See the License for the specific language governing permissions and 13094332d3Sopenharmony_ci * limitations under the License. 14094332d3Sopenharmony_ci */ 15094332d3Sopenharmony_ci 16094332d3Sopenharmony_ci#include "codec_hdi_decode.h" 17094332d3Sopenharmony_ci#include <securec.h> 18094332d3Sopenharmony_ci#include <unistd.h> 19094332d3Sopenharmony_ci#include "codec_omx_ext.h" 20094332d3Sopenharmony_ci#include "hdf_log.h" 21094332d3Sopenharmony_ci#include "v1_0/display_composer_type.h" 22094332d3Sopenharmony_ci#include "v1_0/display_buffer_type.h" 23094332d3Sopenharmony_ci#include "v1_0/include/idisplay_buffer.h" 24094332d3Sopenharmony_ciusing namespace std; 25094332d3Sopenharmony_ciusing namespace OHOS; 26094332d3Sopenharmony_ciusing OHOS::sptr; 27094332d3Sopenharmony_ciusing OHOS::HDI::Base::NativeBuffer; 28094332d3Sopenharmony_ciusing namespace OHOS::HDI::Codec::V3_0; 29094332d3Sopenharmony_ciusing namespace OHOS::HDI::Display::Buffer::V1_0; 30094332d3Sopenharmony_ciusing namespace OHOS::HDI::Display::Composer::V1_0; 31094332d3Sopenharmony_ci#define HDF_LOG_TAG codec_omx_hdi_dec 32094332d3Sopenharmony_ci#define AV_COLOR_FORMAT OMX_COLOR_FormatYUV420SemiPlanar 33094332d3Sopenharmony_ciIDisplayBuffer *CodecHdiDecode::gralloc_ = nullptr; 34094332d3Sopenharmony_ciCodecUtil *CodecHdiDecode::util_; 35094332d3Sopenharmony_cinamespace { 36094332d3Sopenharmony_ciconstexpr int32_t FRAME = 30 << 16; 37094332d3Sopenharmony_ciconstexpr int32_t DENOMINATOR = 2; 38094332d3Sopenharmony_ciconstexpr int32_t NUMERATOR = 3; 39094332d3Sopenharmony_ciconstexpr int32_t START_CODE_OFFSET_ONE = -1; 40094332d3Sopenharmony_ciconstexpr int32_t INIT_BUFFER_CODE = -1; 41094332d3Sopenharmony_ciconstexpr int32_t START_CODE_OFFSET_SEC = -2; 42094332d3Sopenharmony_ciconstexpr int32_t START_CODE_OFFSET_THIRD = -3; 43094332d3Sopenharmony_ciconstexpr int32_t START_CODE_SIZE_FRAME = 4; 44094332d3Sopenharmony_ciconstexpr int32_t START_CODE_SIZE_SLICE = 3; 45094332d3Sopenharmony_ciconstexpr char START_CODE = 0x1; 46094332d3Sopenharmony_ci} // namespace 47094332d3Sopenharmony_ci 48094332d3Sopenharmony_ciCodecHdiDecode::CodecHdiDecode() : fpIn_(nullptr), fpOut_(nullptr) 49094332d3Sopenharmony_ci{ 50094332d3Sopenharmony_ci client_ = nullptr; 51094332d3Sopenharmony_ci callback_ = nullptr; 52094332d3Sopenharmony_ci omxMgr_ = nullptr; 53094332d3Sopenharmony_ci exit_ = false; 54094332d3Sopenharmony_ci width_ = 0; 55094332d3Sopenharmony_ci height_ = 0; 56094332d3Sopenharmony_ci codecMime_ = codecMime::AVC; 57094332d3Sopenharmony_ci count_ = 0; 58094332d3Sopenharmony_ci useBufferHandle_ = false; 59094332d3Sopenharmony_ci useDMABuffer_ = false; 60094332d3Sopenharmony_ci componentId_ = 0; 61094332d3Sopenharmony_ci} 62094332d3Sopenharmony_ci 63094332d3Sopenharmony_ciCodecHdiDecode::~CodecHdiDecode() 64094332d3Sopenharmony_ci{ 65094332d3Sopenharmony_ci if (fpOut_ != nullptr) { 66094332d3Sopenharmony_ci fclose(fpOut_); 67094332d3Sopenharmony_ci fpOut_ = nullptr; 68094332d3Sopenharmony_ci } 69094332d3Sopenharmony_ci 70094332d3Sopenharmony_ci if (fpIn_ != nullptr) { 71094332d3Sopenharmony_ci fclose(fpIn_); 72094332d3Sopenharmony_ci fpIn_ = nullptr; 73094332d3Sopenharmony_ci } 74094332d3Sopenharmony_ci} 75094332d3Sopenharmony_ci 76094332d3Sopenharmony_civoid CodecHdiDecode::WaitForStatusChanged() 77094332d3Sopenharmony_ci{ 78094332d3Sopenharmony_ci unique_lock<mutex> autoLock(statusLock_); 79094332d3Sopenharmony_ci statusCondition_.wait(autoLock); 80094332d3Sopenharmony_ci} 81094332d3Sopenharmony_ci 82094332d3Sopenharmony_civoid CodecHdiDecode::OnStatusChanged() 83094332d3Sopenharmony_ci{ 84094332d3Sopenharmony_ci statusCondition_.notify_one(); 85094332d3Sopenharmony_ci} 86094332d3Sopenharmony_ci 87094332d3Sopenharmony_ciint CodecHdiDecode::GetYuvSize() 88094332d3Sopenharmony_ci{ 89094332d3Sopenharmony_ci return width_ * height_ * NUMERATOR / DENOMINATOR; 90094332d3Sopenharmony_ci} 91094332d3Sopenharmony_ci 92094332d3Sopenharmony_cibool CodecHdiDecode::ReadOnePacket(FILE *fp, char *buf, uint32_t &filledCount) 93094332d3Sopenharmony_ci{ 94094332d3Sopenharmony_ci // read start code first 95094332d3Sopenharmony_ci size_t t = fread(buf, 1, START_CODE_SIZE_FRAME, fp); 96094332d3Sopenharmony_ci if (t < START_CODE_SIZE_FRAME) { 97094332d3Sopenharmony_ci return true; 98094332d3Sopenharmony_ci } 99094332d3Sopenharmony_ci char *temp = buf; 100094332d3Sopenharmony_ci temp += START_CODE_SIZE_FRAME; 101094332d3Sopenharmony_ci bool ret = true; 102094332d3Sopenharmony_ci while (!feof(fp)) { 103094332d3Sopenharmony_ci (void)fread(temp, 1, 1, fp); 104094332d3Sopenharmony_ci if (*temp != START_CODE) { 105094332d3Sopenharmony_ci temp++; 106094332d3Sopenharmony_ci continue; 107094332d3Sopenharmony_ci } 108094332d3Sopenharmony_ci // check start code 109094332d3Sopenharmony_ci if ((temp[START_CODE_OFFSET_ONE] == 0) && (temp[START_CODE_OFFSET_SEC] == 0) && 110094332d3Sopenharmony_ci (temp[START_CODE_OFFSET_THIRD] == 0)) { 111094332d3Sopenharmony_ci fseek(fp, -START_CODE_SIZE_FRAME, SEEK_CUR); 112094332d3Sopenharmony_ci temp -= (START_CODE_SIZE_FRAME - 1); 113094332d3Sopenharmony_ci ret = false; 114094332d3Sopenharmony_ci break; 115094332d3Sopenharmony_ci } 116094332d3Sopenharmony_ci if ((temp[START_CODE_OFFSET_ONE] == 0) && (temp[START_CODE_OFFSET_SEC] == 0)) { 117094332d3Sopenharmony_ci fseek(fp, -START_CODE_SIZE_SLICE, SEEK_CUR); 118094332d3Sopenharmony_ci temp -= (START_CODE_SIZE_SLICE - 1); 119094332d3Sopenharmony_ci ret = false; 120094332d3Sopenharmony_ci break; 121094332d3Sopenharmony_ci } 122094332d3Sopenharmony_ci temp++; 123094332d3Sopenharmony_ci } 124094332d3Sopenharmony_ci filledCount = (temp - buf); 125094332d3Sopenharmony_ci return ret; 126094332d3Sopenharmony_ci} 127094332d3Sopenharmony_ci 128094332d3Sopenharmony_cibool CodecHdiDecode::Init(const CommandOpt &opt) 129094332d3Sopenharmony_ci{ 130094332d3Sopenharmony_ci this->width_ = opt.width; 131094332d3Sopenharmony_ci this->height_ = opt.height; 132094332d3Sopenharmony_ci this->codecMime_ = opt.codec; 133094332d3Sopenharmony_ci this->stride_ = AlignUp(opt.width); 134094332d3Sopenharmony_ci this->useBufferHandle_ = opt.useBufferHandle; 135094332d3Sopenharmony_ci this->useDMABuffer_ = opt.useDMABuffer; 136094332d3Sopenharmony_ci gralloc_ = IDisplayBuffer::Get(); 137094332d3Sopenharmony_ci fpIn_ = fopen(opt.fileInput.c_str(), "rb"); 138094332d3Sopenharmony_ci fpOut_ = fopen(opt.fileOutput.c_str(), "wb+"); 139094332d3Sopenharmony_ci if ((fpIn_ == nullptr) || (fpOut_ == nullptr)) { 140094332d3Sopenharmony_ci HDF_LOGE("%{public}s failed to open file", __func__); 141094332d3Sopenharmony_ci return false; 142094332d3Sopenharmony_ci } 143094332d3Sopenharmony_ci omxMgr_ = ICodecComponentManager::Get(false); 144094332d3Sopenharmony_ci if ((omxMgr_ == nullptr)) { 145094332d3Sopenharmony_ci HDF_LOGE("%{public}s omxMgr_ is null", __func__); 146094332d3Sopenharmony_ci return false; 147094332d3Sopenharmony_ci } 148094332d3Sopenharmony_ci callback_ = new CodecHdiCallback(shared_from_this()); 149094332d3Sopenharmony_ci if ((callback_ == nullptr)) { 150094332d3Sopenharmony_ci HDF_LOGE("%{public}s callback_ is null", __func__); 151094332d3Sopenharmony_ci return false; 152094332d3Sopenharmony_ci } 153094332d3Sopenharmony_ci std::string compName(""); 154094332d3Sopenharmony_ci int32_t err = GetComponentName(compName); 155094332d3Sopenharmony_ci if (err != HDF_SUCCESS) { 156094332d3Sopenharmony_ci HDF_LOGE("%{public}s GetComponentName err", __func__); 157094332d3Sopenharmony_ci return false; 158094332d3Sopenharmony_ci } 159094332d3Sopenharmony_ci err = omxMgr_->CreateComponent(client_, componentId_, compName, reinterpret_cast<int64_t>(this), callback_); 160094332d3Sopenharmony_ci if (err != HDF_SUCCESS) { 161094332d3Sopenharmony_ci HDF_LOGE("%{public}s failed to CreateComponent", __func__); 162094332d3Sopenharmony_ci return false; 163094332d3Sopenharmony_ci } 164094332d3Sopenharmony_ci struct CompVerInfo verInfo; 165094332d3Sopenharmony_ci err = memset_s(&verInfo, sizeof(verInfo), 0, sizeof(verInfo)); 166094332d3Sopenharmony_ci if (err != EOK) { 167094332d3Sopenharmony_ci HDF_LOGE("%{public}s: memset_s verInfo err [%{public}d].", __func__, err); 168094332d3Sopenharmony_ci return false; 169094332d3Sopenharmony_ci } 170094332d3Sopenharmony_ci err = client_->GetComponentVersion(verInfo); 171094332d3Sopenharmony_ci if (err != HDF_SUCCESS) { 172094332d3Sopenharmony_ci HDF_LOGE("%{public}s failed to CreateComponent", __func__); 173094332d3Sopenharmony_ci return false; 174094332d3Sopenharmony_ci } 175094332d3Sopenharmony_ci return true; 176094332d3Sopenharmony_ci} 177094332d3Sopenharmony_ci 178094332d3Sopenharmony_ciint32_t CodecHdiDecode::ConfigPortDefine() 179094332d3Sopenharmony_ci{ 180094332d3Sopenharmony_ci // set width and height on input port 181094332d3Sopenharmony_ci OMX_PARAM_PORTDEFINITIONTYPE param; 182094332d3Sopenharmony_ci if (util_->InitParam(param) != HDF_SUCCESS) { 183094332d3Sopenharmony_ci return HDF_FAILURE; 184094332d3Sopenharmony_ci } 185094332d3Sopenharmony_ci param.nPortIndex = static_cast<uint32_t>(PortIndex::PORT_INDEX_INPUT); 186094332d3Sopenharmony_ci 187094332d3Sopenharmony_ci std::vector<int8_t> inVec, outVec; 188094332d3Sopenharmony_ci util_->ObjectToVector(param, inVec); 189094332d3Sopenharmony_ci auto err = client_->GetParameter(OMX_IndexParamPortDefinition, inVec, outVec); 190094332d3Sopenharmony_ci if (err != HDF_SUCCESS) { 191094332d3Sopenharmony_ci HDF_LOGE("%{public}s failed PortIndex::PORT_INDEX_INPUT, index is OMX_IndexParamPortDefinition", __func__); 192094332d3Sopenharmony_ci return err; 193094332d3Sopenharmony_ci } 194094332d3Sopenharmony_ci util_->VectorToObject(outVec, param); 195094332d3Sopenharmony_ci 196094332d3Sopenharmony_ci HDF_LOGI("PortIndex::PORT_INDEX_INPUT: eCompressionFormat = %{public}d, eColorFormat = %{public}d ", 197094332d3Sopenharmony_ci param.format.video.eCompressionFormat, param.format.video.eColorFormat); 198094332d3Sopenharmony_ci util_->setParmValue(param, width_, height_, stride_); 199094332d3Sopenharmony_ci util_->ObjectToVector(param, inVec); 200094332d3Sopenharmony_ci err = client_->SetParameter(OMX_IndexParamPortDefinition, inVec); 201094332d3Sopenharmony_ci if (err != HDF_SUCCESS) { 202094332d3Sopenharmony_ci HDF_LOGE("%{public}s failed with PortIndex::PORT_INDEX_INPUT, index is OMX_IndexParamPortDefinition", __func__); 203094332d3Sopenharmony_ci return err; 204094332d3Sopenharmony_ci } 205094332d3Sopenharmony_ci 206094332d3Sopenharmony_ci // set width, height and color format on output port 207094332d3Sopenharmony_ci if (util_->InitParam(param) != HDF_SUCCESS) { 208094332d3Sopenharmony_ci return HDF_FAILURE; 209094332d3Sopenharmony_ci } 210094332d3Sopenharmony_ci param.nPortIndex = static_cast<uint32_t>(PortIndex::PORT_INDEX_OUTPUT); 211094332d3Sopenharmony_ci util_->ObjectToVector(param, inVec); 212094332d3Sopenharmony_ci err = client_->GetParameter(OMX_IndexParamPortDefinition, inVec, outVec); 213094332d3Sopenharmony_ci if (err != HDF_SUCCESS) { 214094332d3Sopenharmony_ci HDF_LOGE("%{public}s failed with PortIndex::PORT_INDEX_OUTPUT, index is OMX_IndexParamPortDefinition", 215094332d3Sopenharmony_ci __func__); 216094332d3Sopenharmony_ci return err; 217094332d3Sopenharmony_ci } 218094332d3Sopenharmony_ci util_->VectorToObject(outVec, param); 219094332d3Sopenharmony_ci 220094332d3Sopenharmony_ci HDF_LOGI("PortIndex::PORT_INDEX_OUTPUT eCompressionFormat = %{public}d, eColorFormat=%{public}d", 221094332d3Sopenharmony_ci param.format.video.eCompressionFormat, param.format.video.eColorFormat); 222094332d3Sopenharmony_ci util_->setParmValue(param, width_, height_, stride_); 223094332d3Sopenharmony_ci param.format.video.eColorFormat = AV_COLOR_FORMAT; // YUV420SP 224094332d3Sopenharmony_ci util_->ObjectToVector(param, inVec); 225094332d3Sopenharmony_ci err = client_->SetParameter(OMX_IndexParamPortDefinition, inVec); 226094332d3Sopenharmony_ci if (err != HDF_SUCCESS) { 227094332d3Sopenharmony_ci HDF_LOGE("%{public}s failed with PortIndex::PORT_INDEX_OUTPUT, index is OMX_IndexParamPortDefinition", 228094332d3Sopenharmony_ci __func__); 229094332d3Sopenharmony_ci return err; 230094332d3Sopenharmony_ci } 231094332d3Sopenharmony_ci 232094332d3Sopenharmony_ci return err; 233094332d3Sopenharmony_ci} 234094332d3Sopenharmony_cibool CodecHdiDecode::Configure() 235094332d3Sopenharmony_ci{ 236094332d3Sopenharmony_ci if (ConfigPortDefine() != HDF_SUCCESS) { 237094332d3Sopenharmony_ci return false; 238094332d3Sopenharmony_ci } 239094332d3Sopenharmony_ci 240094332d3Sopenharmony_ci OMX_VIDEO_PARAM_PORTFORMATTYPE param; 241094332d3Sopenharmony_ci if (util_->InitParam(param) != HDF_SUCCESS) { 242094332d3Sopenharmony_ci return false; 243094332d3Sopenharmony_ci } 244094332d3Sopenharmony_ci param.nPortIndex = static_cast<uint32_t>(PortIndex::PORT_INDEX_INPUT); 245094332d3Sopenharmony_ci std::vector<int8_t> inVec, outVec; 246094332d3Sopenharmony_ci util_->ObjectToVector(param, inVec); 247094332d3Sopenharmony_ci auto err = client_->GetParameter(OMX_IndexParamVideoPortFormat, inVec, outVec); 248094332d3Sopenharmony_ci if (err != HDF_SUCCESS) { 249094332d3Sopenharmony_ci HDF_LOGE("%{public}s failed with PortIndex::PORT_INDEX_INPUT", __func__); 250094332d3Sopenharmony_ci return false; 251094332d3Sopenharmony_ci } 252094332d3Sopenharmony_ci util_->VectorToObject(outVec, param); 253094332d3Sopenharmony_ci 254094332d3Sopenharmony_ci HDF_LOGI("set Format PortIndex::PORT_INDEX_INPUT eCompressionFormat = %{public}d, eColorFormat=%{public}d", 255094332d3Sopenharmony_ci param.eCompressionFormat, param.eColorFormat); 256094332d3Sopenharmony_ci param.xFramerate = FRAME; // 30fps,Q16 format 257094332d3Sopenharmony_ci if (codecMime_ == codecMime::AVC) { 258094332d3Sopenharmony_ci param.eCompressionFormat = OMX_VIDEO_CodingAVC; // H264 259094332d3Sopenharmony_ci } else { 260094332d3Sopenharmony_ci param.eCompressionFormat = static_cast<OMX_VIDEO_CODINGTYPE>(CODEC_OMX_VIDEO_CodingHEVC); // H265 261094332d3Sopenharmony_ci } 262094332d3Sopenharmony_ci 263094332d3Sopenharmony_ci util_->ObjectToVector(param, inVec); 264094332d3Sopenharmony_ci err = client_->SetParameter(OMX_IndexParamVideoPortFormat, inVec); 265094332d3Sopenharmony_ci if (err != HDF_SUCCESS) { 266094332d3Sopenharmony_ci HDF_LOGE("%{public}s failed with PortIndex::PORT_INDEX_INPUT", __func__); 267094332d3Sopenharmony_ci return false; 268094332d3Sopenharmony_ci } 269094332d3Sopenharmony_ci 270094332d3Sopenharmony_ci err = CheckAndUseBufferHandle(); 271094332d3Sopenharmony_ci if (err != HDF_SUCCESS) { 272094332d3Sopenharmony_ci HDF_LOGE("%{public}s failed with CheckAndUseBufferHandle", __func__); 273094332d3Sopenharmony_ci return false; 274094332d3Sopenharmony_ci } 275094332d3Sopenharmony_ci 276094332d3Sopenharmony_ci err = CheckAndUseDMABuffer(); 277094332d3Sopenharmony_ci if (err != HDF_SUCCESS) { 278094332d3Sopenharmony_ci HDF_LOGE("%{public}s failed with CheckAndUseDMABuffer", __func__); 279094332d3Sopenharmony_ci return false; 280094332d3Sopenharmony_ci } 281094332d3Sopenharmony_ci return true; 282094332d3Sopenharmony_ci} 283094332d3Sopenharmony_ci 284094332d3Sopenharmony_ciint32_t CodecHdiDecode::CheckSupportBufferType(PortIndex portIndex, CodecBufferType codecBufferType) 285094332d3Sopenharmony_ci{ 286094332d3Sopenharmony_ci //get support buffer 287094332d3Sopenharmony_ci SupportBufferType param; 288094332d3Sopenharmony_ci std::vector<int8_t> inVec, outVec; 289094332d3Sopenharmony_ci if (util_->InitParamInOhos(param) != HDF_SUCCESS) { 290094332d3Sopenharmony_ci return HDF_FAILURE; 291094332d3Sopenharmony_ci } 292094332d3Sopenharmony_ci param.portIndex = static_cast<uint32_t>(portIndex); 293094332d3Sopenharmony_ci 294094332d3Sopenharmony_ci util_->ObjectToVector(param, inVec); 295094332d3Sopenharmony_ci auto err = client_->GetParameter(OMX_IndexParamSupportBufferType, inVec, outVec); 296094332d3Sopenharmony_ci if (err != HDF_SUCCESS) { 297094332d3Sopenharmony_ci HDF_LOGE("%{public}s failed get parameter with portIndex %{public}d and ret %{public}d ", 298094332d3Sopenharmony_ci __func__, portIndex, err); 299094332d3Sopenharmony_ci } 300094332d3Sopenharmony_ci util_->VectorToObject(outVec, param); 301094332d3Sopenharmony_ci if (!(param.bufferTypes & codecBufferType)) { 302094332d3Sopenharmony_ci HDF_LOGE("%{public}s unSupport bufferType %{public}d ,ret is %{public}d", 303094332d3Sopenharmony_ci __func__, codecBufferType, param.bufferTypes); 304094332d3Sopenharmony_ci return HDF_FAILURE; 305094332d3Sopenharmony_ci } 306094332d3Sopenharmony_ci return HDF_SUCCESS; 307094332d3Sopenharmony_ci} 308094332d3Sopenharmony_ci 309094332d3Sopenharmony_ciint32_t CodecHdiDecode::CheckAndUseDMABuffer() 310094332d3Sopenharmony_ci{ 311094332d3Sopenharmony_ci if (!useDMABuffer_) { 312094332d3Sopenharmony_ci return HDF_SUCCESS; 313094332d3Sopenharmony_ci } 314094332d3Sopenharmony_ci return CheckSupportBufferType(PortIndex::PORT_INDEX_INPUT, CODEC_BUFFER_TYPE_DMA_MEM_FD); 315094332d3Sopenharmony_ci} 316094332d3Sopenharmony_ci 317094332d3Sopenharmony_ciint32_t CodecHdiDecode::CheckAndUseBufferHandle() 318094332d3Sopenharmony_ci{ 319094332d3Sopenharmony_ci if (!useBufferHandle_) { 320094332d3Sopenharmony_ci return HDF_SUCCESS; 321094332d3Sopenharmony_ci } 322094332d3Sopenharmony_ci SupportBufferType param; 323094332d3Sopenharmony_ci if (util_->InitParamInOhos(param) != HDF_SUCCESS) { 324094332d3Sopenharmony_ci return HDF_FAILURE; 325094332d3Sopenharmony_ci } 326094332d3Sopenharmony_ci param.portIndex = static_cast<uint32_t>(PortIndex::PORT_INDEX_INPUT); 327094332d3Sopenharmony_ci std::vector<int8_t> inVec, outVec; 328094332d3Sopenharmony_ci util_->ObjectToVector(param, inVec); 329094332d3Sopenharmony_ci auto err = client_->GetParameter(OMX_IndexParamSupportBufferType, inVec, outVec); 330094332d3Sopenharmony_ci if (err != HDF_SUCCESS) { 331094332d3Sopenharmony_ci HDF_LOGE("OMX_GetParameter OMX_IndexParamSupportBufferType in err [%{public}x]", err); 332094332d3Sopenharmony_ci return err; 333094332d3Sopenharmony_ci } 334094332d3Sopenharmony_ci util_->VectorToObject(outVec, param); 335094332d3Sopenharmony_ci 336094332d3Sopenharmony_ci if (util_->InitParamInOhos(param) != HDF_SUCCESS) { 337094332d3Sopenharmony_ci return HDF_FAILURE; 338094332d3Sopenharmony_ci } 339094332d3Sopenharmony_ci param.portIndex = static_cast<uint32_t>(PortIndex::PORT_INDEX_OUTPUT); 340094332d3Sopenharmony_ci util_->ObjectToVector(param, inVec); 341094332d3Sopenharmony_ci err = client_->GetParameter(OMX_IndexParamSupportBufferType, inVec, outVec); 342094332d3Sopenharmony_ci if (err != HDF_SUCCESS) { 343094332d3Sopenharmony_ci HDF_LOGE("OMX_GetParameter OMX_IndexParamSupportBufferType out err [%{public}x]", err); 344094332d3Sopenharmony_ci return err; 345094332d3Sopenharmony_ci } 346094332d3Sopenharmony_ci util_->VectorToObject(outVec, param); 347094332d3Sopenharmony_ci 348094332d3Sopenharmony_ci GetBufferHandleUsageParams usage; 349094332d3Sopenharmony_ci if (util_->InitParamInOhos(usage) != HDF_SUCCESS) { 350094332d3Sopenharmony_ci return HDF_FAILURE; 351094332d3Sopenharmony_ci } 352094332d3Sopenharmony_ci usage.portIndex = static_cast<uint32_t>(PortIndex::PORT_INDEX_OUTPUT); 353094332d3Sopenharmony_ci util_->ObjectToVector(usage, inVec); 354094332d3Sopenharmony_ci err = client_->GetParameter(OMX_IndexParamGetBufferHandleUsage, inVec, outVec); 355094332d3Sopenharmony_ci if (err != HDF_SUCCESS) { 356094332d3Sopenharmony_ci HDF_LOGE("OMX_GetParameter OMX_IndexParamGetBufferHandleUsage out err [%{public}x]", err); 357094332d3Sopenharmony_ci return err; 358094332d3Sopenharmony_ci } 359094332d3Sopenharmony_ci util_->VectorToObject(outVec, usage); 360094332d3Sopenharmony_ci 361094332d3Sopenharmony_ci UseBufferType type; 362094332d3Sopenharmony_ci if (util_->InitParamInOhos(type) != HDF_SUCCESS) { 363094332d3Sopenharmony_ci return HDF_FAILURE; 364094332d3Sopenharmony_ci } 365094332d3Sopenharmony_ci type.portIndex = static_cast<uint32_t>(PortIndex::PORT_INDEX_OUTPUT); 366094332d3Sopenharmony_ci type.bufferType = CODEC_BUFFER_TYPE_HANDLE; 367094332d3Sopenharmony_ci util_->ObjectToVector(type, inVec); 368094332d3Sopenharmony_ci err = client_->SetParameter(OMX_IndexParamUseBufferType, inVec); 369094332d3Sopenharmony_ci if (err != HDF_SUCCESS) { 370094332d3Sopenharmony_ci HDF_LOGE("OMX_SetParameter OMX_IndexParamUseBufferType out, err [%{public}x]", err); 371094332d3Sopenharmony_ci return err; 372094332d3Sopenharmony_ci } 373094332d3Sopenharmony_ci return err; 374094332d3Sopenharmony_ci} 375094332d3Sopenharmony_ci 376094332d3Sopenharmony_cibool CodecHdiDecode::UseBuffers() 377094332d3Sopenharmony_ci{ 378094332d3Sopenharmony_ci HDF_LOGI("...command to IDLE...."); 379094332d3Sopenharmony_ci std::vector<int8_t> cmdData; 380094332d3Sopenharmony_ci auto err = client_->SendCommand(CODEC_COMMAND_STATE_SET, CODEC_STATE_IDLE, cmdData); 381094332d3Sopenharmony_ci if (err != HDF_SUCCESS) { 382094332d3Sopenharmony_ci HDF_LOGE("%{public}s failed to SendCommand with CODEC_COMMAND_STATE_SET:CODEC_STATE_IDLE", __func__); 383094332d3Sopenharmony_ci return false; 384094332d3Sopenharmony_ci } 385094332d3Sopenharmony_ci 386094332d3Sopenharmony_ci err = UseBufferOnPort(PortIndex::PORT_INDEX_INPUT); 387094332d3Sopenharmony_ci if (err != HDF_SUCCESS) { 388094332d3Sopenharmony_ci HDF_LOGE("%{public}s UseBufferOnPort PortIndex::PORT_INDEX_INPUT error", __func__); 389094332d3Sopenharmony_ci return false; 390094332d3Sopenharmony_ci } 391094332d3Sopenharmony_ci 392094332d3Sopenharmony_ci err = UseBufferOnPort(PortIndex::PORT_INDEX_OUTPUT); 393094332d3Sopenharmony_ci if (err != HDF_SUCCESS) { 394094332d3Sopenharmony_ci HDF_LOGE("%{public}s UseBufferOnPort PortIndex::PORT_INDEX_OUTPUT error", __func__); 395094332d3Sopenharmony_ci return false; 396094332d3Sopenharmony_ci } 397094332d3Sopenharmony_ci 398094332d3Sopenharmony_ci HDF_LOGI("Wait for CODEC_STATE_IDLE status"); 399094332d3Sopenharmony_ci CodecStateType status = CODEC_STATE_INVALID; 400094332d3Sopenharmony_ci err = client_->GetState(status); 401094332d3Sopenharmony_ci if (err != HDF_SUCCESS) { 402094332d3Sopenharmony_ci HDF_LOGE("%{public}s GetState err [%{public}x]", __func__, err); 403094332d3Sopenharmony_ci return false; 404094332d3Sopenharmony_ci } 405094332d3Sopenharmony_ci if (status != CODEC_STATE_IDLE) { 406094332d3Sopenharmony_ci HDF_LOGI("Wait for CODEC_STATE_LOADED status"); 407094332d3Sopenharmony_ci this->WaitForStatusChanged(); 408094332d3Sopenharmony_ci } else { 409094332d3Sopenharmony_ci HDF_LOGI(" status is %{public}d", status); 410094332d3Sopenharmony_ci } 411094332d3Sopenharmony_ci 412094332d3Sopenharmony_ci return true; 413094332d3Sopenharmony_ci} 414094332d3Sopenharmony_ci 415094332d3Sopenharmony_ciint32_t CodecHdiDecode::UseBufferOnPort(PortIndex portIndex, int bufferCount, int bufferSize) 416094332d3Sopenharmony_ci{ 417094332d3Sopenharmony_ci if (bufferCount <= 0 || bufferSize <= 0) { 418094332d3Sopenharmony_ci HDF_LOGE("UseBufferOnPort bufferCount <= 0 or bufferSize <= 0"); 419094332d3Sopenharmony_ci return HDF_ERR_INVALID_PARAM; 420094332d3Sopenharmony_ci } 421094332d3Sopenharmony_ci for (int i = 0; i < bufferCount; i++) { 422094332d3Sopenharmony_ci std::shared_ptr<OmxCodecBuffer> omxBuffer = std::make_shared<OmxCodecBuffer>(); 423094332d3Sopenharmony_ci omxBuffer->size = sizeof(OmxCodecBuffer); 424094332d3Sopenharmony_ci omxBuffer->version.version.majorVersion = 1; 425094332d3Sopenharmony_ci omxBuffer->bufferType = CODEC_BUFFER_TYPE_AVSHARE_MEM_FD; 426094332d3Sopenharmony_ci int fd = AshmemCreate(0, bufferSize); 427094332d3Sopenharmony_ci shared_ptr<Ashmem> sharedMem = make_shared<Ashmem>(fd, bufferSize); 428094332d3Sopenharmony_ci omxBuffer->fd = fd; 429094332d3Sopenharmony_ci omxBuffer->bufferhandle = nullptr; 430094332d3Sopenharmony_ci omxBuffer->allocLen = bufferSize; 431094332d3Sopenharmony_ci omxBuffer->fenceFd = -1; 432094332d3Sopenharmony_ci omxBuffer->pts = 0; 433094332d3Sopenharmony_ci omxBuffer->flag = 0; 434094332d3Sopenharmony_ci 435094332d3Sopenharmony_ci if (portIndex == PortIndex::PORT_INDEX_INPUT) { 436094332d3Sopenharmony_ci omxBuffer->type = READ_ONLY_TYPE; 437094332d3Sopenharmony_ci sharedMem->MapReadAndWriteAshmem(); 438094332d3Sopenharmony_ci } else { 439094332d3Sopenharmony_ci omxBuffer->type = READ_WRITE_TYPE; 440094332d3Sopenharmony_ci sharedMem->MapReadOnlyAshmem(); 441094332d3Sopenharmony_ci } 442094332d3Sopenharmony_ci OmxCodecBuffer outBuffer; 443094332d3Sopenharmony_ci auto err = client_->UseBuffer(static_cast<uint32_t>(portIndex), *omxBuffer.get(), outBuffer); 444094332d3Sopenharmony_ci if (err != HDF_SUCCESS) { 445094332d3Sopenharmony_ci HDF_LOGE("%{public}s failed to UseBuffer with portIndex[%{public}d]", __func__, portIndex); 446094332d3Sopenharmony_ci sharedMem->UnmapAshmem(); 447094332d3Sopenharmony_ci sharedMem->CloseAshmem(); 448094332d3Sopenharmony_ci sharedMem = nullptr; 449094332d3Sopenharmony_ci return err; 450094332d3Sopenharmony_ci } 451094332d3Sopenharmony_ci omxBuffer->bufferId = outBuffer.bufferId; 452094332d3Sopenharmony_ci omxBuffer->fd = -1; 453094332d3Sopenharmony_ci HDF_LOGI("UseBuffer returned bufferID [%{public}d]", omxBuffer->bufferId); 454094332d3Sopenharmony_ci 455094332d3Sopenharmony_ci std::shared_ptr<BufferInfo> bufferInfo = std::make_shared<BufferInfo>(); 456094332d3Sopenharmony_ci bufferInfo->omxBuffer = omxBuffer; 457094332d3Sopenharmony_ci bufferInfo->avSharedPtr = sharedMem; 458094332d3Sopenharmony_ci bufferInfo->portIndex = portIndex; 459094332d3Sopenharmony_ci omxBuffers_.emplace(std::make_pair(omxBuffer->bufferId, bufferInfo)); 460094332d3Sopenharmony_ci if (portIndex == PortIndex::PORT_INDEX_INPUT) { 461094332d3Sopenharmony_ci unUsedInBuffers_.push_back(omxBuffer->bufferId); 462094332d3Sopenharmony_ci } else { 463094332d3Sopenharmony_ci unUsedOutBuffers_.push_back(omxBuffer->bufferId); 464094332d3Sopenharmony_ci } 465094332d3Sopenharmony_ci } 466094332d3Sopenharmony_ci 467094332d3Sopenharmony_ci return HDF_SUCCESS; 468094332d3Sopenharmony_ci} 469094332d3Sopenharmony_ci 470094332d3Sopenharmony_ciint32_t CodecHdiDecode::UseBufferOnPort(PortIndex portIndex) 471094332d3Sopenharmony_ci{ 472094332d3Sopenharmony_ci HDF_LOGI("%{public}s enter, portIndex = %{public}d", __func__, portIndex); 473094332d3Sopenharmony_ci int bufferSize = 0; 474094332d3Sopenharmony_ci int bufferCount = 0; 475094332d3Sopenharmony_ci bool portEnable = false; 476094332d3Sopenharmony_ci 477094332d3Sopenharmony_ci OMX_PARAM_PORTDEFINITIONTYPE param; 478094332d3Sopenharmony_ci if (util_->InitParam(param) != HDF_SUCCESS) { 479094332d3Sopenharmony_ci return HDF_FAILURE; 480094332d3Sopenharmony_ci } 481094332d3Sopenharmony_ci param.nPortIndex = static_cast<OMX_U32>(portIndex); 482094332d3Sopenharmony_ci 483094332d3Sopenharmony_ci std::vector<int8_t> inVec, outVec; 484094332d3Sopenharmony_ci util_->ObjectToVector(param, inVec); 485094332d3Sopenharmony_ci auto err = client_->GetParameter(OMX_IndexParamPortDefinition, inVec, outVec); 486094332d3Sopenharmony_ci if (err != HDF_SUCCESS) { 487094332d3Sopenharmony_ci HDF_LOGE("%{public}s failed to GetParameter with OMX_IndexParamPortDefinition : portIndex[%{public}d]", 488094332d3Sopenharmony_ci __func__, portIndex); 489094332d3Sopenharmony_ci return err; 490094332d3Sopenharmony_ci } 491094332d3Sopenharmony_ci util_->VectorToObject(outVec, param); 492094332d3Sopenharmony_ci 493094332d3Sopenharmony_ci bufferSize = param.nBufferSize; 494094332d3Sopenharmony_ci bufferCount = param.nBufferCountActual; 495094332d3Sopenharmony_ci portEnable = param.bEnabled; 496094332d3Sopenharmony_ci HDF_LOGI("buffer index [%{public}d], buffer size [%{public}d], " 497094332d3Sopenharmony_ci "buffer count [%{public}d], portEnable[%{public}d], ret [%{public}d]", 498094332d3Sopenharmony_ci portIndex, bufferSize, bufferCount, portEnable, err); 499094332d3Sopenharmony_ci if (useBufferHandle_ && portIndex == PortIndex::PORT_INDEX_OUTPUT) { 500094332d3Sopenharmony_ci err = UseBufferHandle(bufferCount, bufferSize); 501094332d3Sopenharmony_ci } else if (useDMABuffer_ && portIndex == PortIndex::PORT_INDEX_INPUT) { 502094332d3Sopenharmony_ci err = UseDMABuffer(portIndex, bufferCount, bufferSize); 503094332d3Sopenharmony_ci } else { 504094332d3Sopenharmony_ci err = UseBufferOnPort(portIndex, bufferCount, bufferSize); 505094332d3Sopenharmony_ci } 506094332d3Sopenharmony_ci 507094332d3Sopenharmony_ci if (err != HDF_SUCCESS) { 508094332d3Sopenharmony_ci HDF_LOGE("%{public}s UseBufferOnPort err[%{public}x]", __func__, err); 509094332d3Sopenharmony_ci return err; 510094332d3Sopenharmony_ci } 511094332d3Sopenharmony_ci // set port enable 512094332d3Sopenharmony_ci if (!portEnable) { 513094332d3Sopenharmony_ci err = client_->SendCommand(CODEC_COMMAND_PORT_ENABLE, static_cast<uint32_t>(portIndex), {}); 514094332d3Sopenharmony_ci if (err != HDF_SUCCESS) { 515094332d3Sopenharmony_ci HDF_LOGE("%{public}s SendCommand OMX_CommandPortEnable::PortIndex::PORT_INDEX_INPUT error", __func__); 516094332d3Sopenharmony_ci return err; 517094332d3Sopenharmony_ci } 518094332d3Sopenharmony_ci } 519094332d3Sopenharmony_ci return HDF_SUCCESS; 520094332d3Sopenharmony_ci} 521094332d3Sopenharmony_ci 522094332d3Sopenharmony_ciint32_t CodecHdiDecode::UseDMABuffer(PortIndex portIndex, int bufferCount, int bufferSize) 523094332d3Sopenharmony_ci{ 524094332d3Sopenharmony_ci if (bufferCount <= 0 || bufferSize <= 0) { 525094332d3Sopenharmony_ci HDF_LOGE("UseDMABuffer bufferCount <= 0 or bufferSize <= 0"); 526094332d3Sopenharmony_ci return HDF_ERR_INVALID_PARAM; 527094332d3Sopenharmony_ci } 528094332d3Sopenharmony_ci for (int i = 0; i < bufferCount; i++) { 529094332d3Sopenharmony_ci std::shared_ptr<OmxCodecBuffer> omxBuffer = std::make_shared<OmxCodecBuffer>(); 530094332d3Sopenharmony_ci omxBuffer->size = sizeof(OmxCodecBuffer); 531094332d3Sopenharmony_ci omxBuffer->version.version.majorVersion = 1; 532094332d3Sopenharmony_ci omxBuffer->bufferType = CODEC_BUFFER_TYPE_DMA_MEM_FD; 533094332d3Sopenharmony_ci omxBuffer->fd = INIT_BUFFER_CODE; 534094332d3Sopenharmony_ci omxBuffer->bufferhandle = nullptr; 535094332d3Sopenharmony_ci omxBuffer->allocLen = bufferSize; 536094332d3Sopenharmony_ci omxBuffer->fenceFd = INIT_BUFFER_CODE; 537094332d3Sopenharmony_ci omxBuffer->pts = 0; 538094332d3Sopenharmony_ci omxBuffer->flag = 0; 539094332d3Sopenharmony_ci omxBuffer->type = READ_WRITE_TYPE; 540094332d3Sopenharmony_ci 541094332d3Sopenharmony_ci OmxCodecBuffer outBuffer; 542094332d3Sopenharmony_ci auto err = client_->AllocateBuffer(static_cast<uint32_t>(portIndex), *omxBuffer.get(), outBuffer); 543094332d3Sopenharmony_ci if (err != HDF_SUCCESS) { 544094332d3Sopenharmony_ci HDF_LOGE("%{public}s failed to UseBuffer with portIndex[%{public}d]", __func__, portIndex); 545094332d3Sopenharmony_ci return err; 546094332d3Sopenharmony_ci } 547094332d3Sopenharmony_ci omxBuffer->bufferId = outBuffer.bufferId; 548094332d3Sopenharmony_ci HDF_LOGI("UseBuffer returned bufferID [%{public}d]", omxBuffer->bufferId); 549094332d3Sopenharmony_ci 550094332d3Sopenharmony_ci std::shared_ptr<BufferInfo> bufferInfo = std::make_shared<BufferInfo>(); 551094332d3Sopenharmony_ci bufferInfo->omxBuffer = omxBuffer; 552094332d3Sopenharmony_ci bufferInfo->portIndex = portIndex; 553094332d3Sopenharmony_ci bufferInfo->omxBuffer->fd = outBuffer.fd; 554094332d3Sopenharmony_ci omxBuffers_.insert(std::make_pair(omxBuffer->bufferId, bufferInfo)); 555094332d3Sopenharmony_ci unUsedInBuffers_.push_back(omxBuffer->bufferId); 556094332d3Sopenharmony_ci 557094332d3Sopenharmony_ci void *addr = mmap(nullptr, static_cast<size_t>(bufferInfo->omxBuffer->allocLen), 558094332d3Sopenharmony_ci PROT_READ | PROT_WRITE, MAP_SHARED, bufferInfo->omxBuffer->fd, 0); 559094332d3Sopenharmony_ci if (addr == nullptr) { 560094332d3Sopenharmony_ci HDF_LOGE("%{public}s mmap fail fd %{public}d", __func__, omxBuffer->fd); 561094332d3Sopenharmony_ci return HDF_FAILURE; 562094332d3Sopenharmony_ci } else { 563094332d3Sopenharmony_ci addrs_[omxBuffer->bufferId] = addr; 564094332d3Sopenharmony_ci } 565094332d3Sopenharmony_ci } 566094332d3Sopenharmony_ci return HDF_SUCCESS; 567094332d3Sopenharmony_ci} 568094332d3Sopenharmony_ci 569094332d3Sopenharmony_ciint32_t CodecHdiDecode::UseBufferHandle(int bufferCount, int bufferSize) 570094332d3Sopenharmony_ci{ 571094332d3Sopenharmony_ci if (bufferCount <= 0 || bufferSize <= 0 || gralloc_ == nullptr) { 572094332d3Sopenharmony_ci return HDF_ERR_INVALID_PARAM; 573094332d3Sopenharmony_ci } 574094332d3Sopenharmony_ci AllocInfo alloc = {.width = this->stride_, 575094332d3Sopenharmony_ci .height = this->height_, 576094332d3Sopenharmony_ci .usage = HBM_USE_CPU_READ | HBM_USE_CPU_WRITE | HBM_USE_MEM_DMA, 577094332d3Sopenharmony_ci .format = PIXEL_FMT_YCBCR_420_SP}; 578094332d3Sopenharmony_ci for (int i = 0; i < bufferCount; i++) { 579094332d3Sopenharmony_ci std::shared_ptr<OmxCodecBuffer> omxBuffer = std::make_shared<OmxCodecBuffer>(); 580094332d3Sopenharmony_ci omxBuffer->size = sizeof(OmxCodecBuffer); 581094332d3Sopenharmony_ci omxBuffer->version.version.majorVersion = 1; 582094332d3Sopenharmony_ci omxBuffer->bufferType = CODEC_BUFFER_TYPE_HANDLE; 583094332d3Sopenharmony_ci BufferHandle *bufferHandle = nullptr; 584094332d3Sopenharmony_ci int32_t err = gralloc_->AllocMem(alloc, bufferHandle); 585094332d3Sopenharmony_ci HDF_LOGI("%{public}s AlloceMem ret val ret[%{public}d]", __func__, err); 586094332d3Sopenharmony_ci if (DISPLAY_SUCCESS != err) { 587094332d3Sopenharmony_ci HDF_LOGE("%{public}s AllocMem error", __func__); 588094332d3Sopenharmony_ci return err; 589094332d3Sopenharmony_ci } 590094332d3Sopenharmony_ci omxBuffer->fd = -1; 591094332d3Sopenharmony_ci omxBuffer->allocLen = bufferSize; 592094332d3Sopenharmony_ci omxBuffer->fenceFd = -1; // check use -1 first with no window 593094332d3Sopenharmony_ci omxBuffer->pts = 0; 594094332d3Sopenharmony_ci omxBuffer->flag = 0; 595094332d3Sopenharmony_ci omxBuffer->bufferhandle = new NativeBuffer(bufferHandle); 596094332d3Sopenharmony_ci OmxCodecBuffer outBuffer; 597094332d3Sopenharmony_ci err = client_->UseBuffer(static_cast<uint32_t>(PortIndex::PORT_INDEX_OUTPUT), 598094332d3Sopenharmony_ci *omxBuffer.get(), outBuffer); 599094332d3Sopenharmony_ci omxBuffer->bufferhandle = nullptr; 600094332d3Sopenharmony_ci if (err != HDF_SUCCESS) { 601094332d3Sopenharmony_ci HDF_LOGE("%{public}s failed to UseBuffer with output port]", __func__); 602094332d3Sopenharmony_ci return err; 603094332d3Sopenharmony_ci } 604094332d3Sopenharmony_ci omxBuffer->bufferId = outBuffer.bufferId; 605094332d3Sopenharmony_ci HDF_LOGI("UseBuffer returned bufferID [%{public}d]", omxBuffer->bufferId); 606094332d3Sopenharmony_ci 607094332d3Sopenharmony_ci std::shared_ptr<BufferInfo> bufferInfo = std::make_shared<BufferInfo>(); 608094332d3Sopenharmony_ci bufferInfo->omxBuffer = omxBuffer; 609094332d3Sopenharmony_ci bufferInfo->setBufferHandle(bufferHandle); 610094332d3Sopenharmony_ci bufferInfo->portIndex = PortIndex::PORT_INDEX_OUTPUT; 611094332d3Sopenharmony_ci omxBuffers_.emplace(std::make_pair(omxBuffer->bufferId, bufferInfo)); 612094332d3Sopenharmony_ci unUsedOutBuffers_.push_back(omxBuffer->bufferId); 613094332d3Sopenharmony_ci } 614094332d3Sopenharmony_ci return HDF_SUCCESS; 615094332d3Sopenharmony_ci} 616094332d3Sopenharmony_ci 617094332d3Sopenharmony_civoid CodecHdiDecode::FreeBuffers() 618094332d3Sopenharmony_ci{ 619094332d3Sopenharmony_ci // command to loaded 620094332d3Sopenharmony_ci (void)client_->SendCommand(CODEC_COMMAND_STATE_SET, CODEC_STATE_LOADED, {}); 621094332d3Sopenharmony_ci 622094332d3Sopenharmony_ci // release all the buffers 623094332d3Sopenharmony_ci auto iter = omxBuffers_.begin(); 624094332d3Sopenharmony_ci while (iter != omxBuffers_.end()) { 625094332d3Sopenharmony_ci auto bufferInfo = iter->second; 626094332d3Sopenharmony_ci iter = omxBuffers_.erase(iter); 627094332d3Sopenharmony_ci (void)client_->FreeBuffer(static_cast<uint32_t>(bufferInfo->portIndex), *bufferInfo->omxBuffer.get()); 628094332d3Sopenharmony_ci bufferInfo = nullptr; 629094332d3Sopenharmony_ci } 630094332d3Sopenharmony_ci 631094332d3Sopenharmony_ci unUsedInBuffers_.clear(); 632094332d3Sopenharmony_ci unUsedOutBuffers_.clear(); 633094332d3Sopenharmony_ci 634094332d3Sopenharmony_ci CodecStateType status = CODEC_STATE_INVALID; 635094332d3Sopenharmony_ci int32_t tryCount = 3; 636094332d3Sopenharmony_ci do { 637094332d3Sopenharmony_ci int32_t err = client_->GetState(status); 638094332d3Sopenharmony_ci if (err != HDF_SUCCESS) { 639094332d3Sopenharmony_ci HDF_LOGE("%s GetState error [%{public}x]", __func__, err); 640094332d3Sopenharmony_ci break; 641094332d3Sopenharmony_ci } 642094332d3Sopenharmony_ci if (status != CODEC_STATE_LOADED) { 643094332d3Sopenharmony_ci HDF_LOGI("Wait for OMX_StateLoaded status"); 644094332d3Sopenharmony_ci this->WaitForStatusChanged(); 645094332d3Sopenharmony_ci } 646094332d3Sopenharmony_ci tryCount--; 647094332d3Sopenharmony_ci } while ((status != CODEC_STATE_LOADED) && (tryCount > 0)); 648094332d3Sopenharmony_ci} 649094332d3Sopenharmony_ci 650094332d3Sopenharmony_civoid CodecHdiDecode::Release() 651094332d3Sopenharmony_ci{ 652094332d3Sopenharmony_ci omxMgr_->DestroyComponent(componentId_); 653094332d3Sopenharmony_ci client_ = nullptr; 654094332d3Sopenharmony_ci callback_ = nullptr; 655094332d3Sopenharmony_ci omxMgr_ = nullptr; 656094332d3Sopenharmony_ci} 657094332d3Sopenharmony_ci 658094332d3Sopenharmony_cibool CodecHdiDecode::FillAllTheBuffer() 659094332d3Sopenharmony_ci{ 660094332d3Sopenharmony_ci for (auto bufferId : unUsedOutBuffers_) { 661094332d3Sopenharmony_ci HDF_LOGI("fillThisBUffer, bufferid [%{public}d]", bufferId); 662094332d3Sopenharmony_ci auto iter = omxBuffers_.find(bufferId); 663094332d3Sopenharmony_ci if (iter != omxBuffers_.end()) { 664094332d3Sopenharmony_ci auto bufferInfo = iter->second; 665094332d3Sopenharmony_ci auto buffer = bufferInfo->omxBuffer.get(); 666094332d3Sopenharmony_ci auto err = client_->FillThisBuffer(*buffer); 667094332d3Sopenharmony_ci if (err != HDF_SUCCESS) { 668094332d3Sopenharmony_ci HDF_LOGE("%{public}s FillThisBuffer error", __func__); 669094332d3Sopenharmony_ci return false; 670094332d3Sopenharmony_ci } 671094332d3Sopenharmony_ci } 672094332d3Sopenharmony_ci } 673094332d3Sopenharmony_ci return true; 674094332d3Sopenharmony_ci} 675094332d3Sopenharmony_ci 676094332d3Sopenharmony_ciint CodecHdiDecode::GetFreeBufferId() 677094332d3Sopenharmony_ci{ 678094332d3Sopenharmony_ci int bufferID = -1; 679094332d3Sopenharmony_ci unique_lock<mutex> ulk(lockInputBuffers_); 680094332d3Sopenharmony_ci size_t nSize = this->unUsedInBuffers_.size(); 681094332d3Sopenharmony_ci if (nSize != 0) { 682094332d3Sopenharmony_ci bufferID = unUsedInBuffers_.front(); 683094332d3Sopenharmony_ci unUsedInBuffers_.pop_front(); 684094332d3Sopenharmony_ci } 685094332d3Sopenharmony_ci return bufferID; 686094332d3Sopenharmony_ci} 687094332d3Sopenharmony_ci 688094332d3Sopenharmony_ciint32_t CodecHdiDecode::GetComponentName(std::string &compName) 689094332d3Sopenharmony_ci{ 690094332d3Sopenharmony_ci AvCodecRole role = AvCodecRole::MEDIA_ROLETYPE_VIDEO_AVC; 691094332d3Sopenharmony_ci if (codecMime_ == codecMime::HEVC) { 692094332d3Sopenharmony_ci role = AvCodecRole::MEDIA_ROLETYPE_VIDEO_HEVC; 693094332d3Sopenharmony_ci } 694094332d3Sopenharmony_ci 695094332d3Sopenharmony_ci int32_t count = 0; 696094332d3Sopenharmony_ci auto err = omxMgr_->GetComponentNum(count); 697094332d3Sopenharmony_ci if (err != HDF_SUCCESS || count <= 0) { 698094332d3Sopenharmony_ci HDF_LOGE("%{public}s GetComponentNum return %{public}d, count = %{public}d", __func__, err, count); 699094332d3Sopenharmony_ci return HDF_FAILURE; 700094332d3Sopenharmony_ci } 701094332d3Sopenharmony_ci std::vector<CodecCompCapability> caps; 702094332d3Sopenharmony_ci err = omxMgr_->GetComponentCapabilityList(caps, count); 703094332d3Sopenharmony_ci if (err != HDF_SUCCESS) { 704094332d3Sopenharmony_ci HDF_LOGE("%{public}s GetComponentCapabilityList return %{public}d", __func__, err); 705094332d3Sopenharmony_ci return err; 706094332d3Sopenharmony_ci } 707094332d3Sopenharmony_ci err = HDF_FAILURE; 708094332d3Sopenharmony_ci for (auto cap : caps) { 709094332d3Sopenharmony_ci if (cap.type == CodecType::VIDEO_DECODER && cap.role == role) { 710094332d3Sopenharmony_ci compName = cap.compName; 711094332d3Sopenharmony_ci err = HDF_SUCCESS; 712094332d3Sopenharmony_ci break; 713094332d3Sopenharmony_ci } 714094332d3Sopenharmony_ci } 715094332d3Sopenharmony_ci return err; 716094332d3Sopenharmony_ci} 717094332d3Sopenharmony_civoid CodecHdiDecode::Run() 718094332d3Sopenharmony_ci{ 719094332d3Sopenharmony_ci HDF_LOGI("...command to CODEC_STATE_EXECUTING...."); 720094332d3Sopenharmony_ci auto err = client_->SendCommand(CODEC_COMMAND_STATE_SET, CODEC_STATE_EXECUTING, {}); 721094332d3Sopenharmony_ci if (err != HDF_SUCCESS) { 722094332d3Sopenharmony_ci HDF_LOGE("%{public}s failed to SendCommand with CODEC_COMMAND_STATE_SET:CODEC_STATE_IDLE", __func__); 723094332d3Sopenharmony_ci return; 724094332d3Sopenharmony_ci } 725094332d3Sopenharmony_ci 726094332d3Sopenharmony_ci if (!FillAllTheBuffer()) { 727094332d3Sopenharmony_ci HDF_LOGE("%{public}s FillAllTheBuffer error", __func__); 728094332d3Sopenharmony_ci return; 729094332d3Sopenharmony_ci } 730094332d3Sopenharmony_ci 731094332d3Sopenharmony_ci auto t1 = std::chrono::system_clock::now(); 732094332d3Sopenharmony_ci bool eosFlag = false; 733094332d3Sopenharmony_ci while (!eosFlag) { 734094332d3Sopenharmony_ci if (this->exit_) { 735094332d3Sopenharmony_ci break; 736094332d3Sopenharmony_ci } 737094332d3Sopenharmony_ci int bufferID = GetFreeBufferId(); 738094332d3Sopenharmony_ci if (bufferID < 0) { 739094332d3Sopenharmony_ci usleep(10000); // 10000 for wait 10ms 740094332d3Sopenharmony_ci continue; 741094332d3Sopenharmony_ci } 742094332d3Sopenharmony_ci auto iter = omxBuffers_.find(bufferID); 743094332d3Sopenharmony_ci if (iter == omxBuffers_.end()) { 744094332d3Sopenharmony_ci continue; 745094332d3Sopenharmony_ci } 746094332d3Sopenharmony_ci auto bufferInfo = iter->second; 747094332d3Sopenharmony_ci 748094332d3Sopenharmony_ci if (!FillCodecBuffer(bufferInfo, eosFlag)) { 749094332d3Sopenharmony_ci break; 750094332d3Sopenharmony_ci } 751094332d3Sopenharmony_ci if (eosFlag) { 752094332d3Sopenharmony_ci bufferInfo->omxBuffer->flag = OMX_BUFFERFLAG_EOS; 753094332d3Sopenharmony_ci } 754094332d3Sopenharmony_ci err = client_->EmptyThisBuffer(*bufferInfo->omxBuffer.get()); 755094332d3Sopenharmony_ci if (err != HDF_SUCCESS) { 756094332d3Sopenharmony_ci HDF_LOGE("%{public}s EmptyThisBuffer error", __func__); 757094332d3Sopenharmony_ci return; 758094332d3Sopenharmony_ci } 759094332d3Sopenharmony_ci } 760094332d3Sopenharmony_ci // wait 761094332d3Sopenharmony_ci while (!this->exit_) { 762094332d3Sopenharmony_ci usleep(10000); // 10000 for wait 10ms 763094332d3Sopenharmony_ci } 764094332d3Sopenharmony_ci auto t2 = std::chrono::system_clock::now(); 765094332d3Sopenharmony_ci std::chrono::duration<double> diff = t2 - t1; 766094332d3Sopenharmony_ci HDF_LOGI("cost %{public}f, count=%{public}d", diff.count(), count_); 767094332d3Sopenharmony_ci (void)client_->SendCommand(CODEC_COMMAND_STATE_SET, CODEC_STATE_IDLE, {}); 768094332d3Sopenharmony_ci return; 769094332d3Sopenharmony_ci} 770094332d3Sopenharmony_ci 771094332d3Sopenharmony_cibool CodecHdiDecode::FillCodecBuffer(std::shared_ptr<BufferInfo> bufferInfo, bool &eosFlag) 772094332d3Sopenharmony_ci{ 773094332d3Sopenharmony_ci if (useDMABuffer_) { 774094332d3Sopenharmony_ci auto ret = addrs_.find(bufferInfo->omxBuffer->bufferId); 775094332d3Sopenharmony_ci if (ret != addrs_.end()) { 776094332d3Sopenharmony_ci eosFlag = this->ReadOnePacket(fpIn_, static_cast<char *>(ret->second), bufferInfo->omxBuffer->filledLen); 777094332d3Sopenharmony_ci bufferInfo->omxBuffer->offset = 0; 778094332d3Sopenharmony_ci } 779094332d3Sopenharmony_ci } else { 780094332d3Sopenharmony_ci void *sharedAddr = const_cast<void *>(bufferInfo->avSharedPtr->ReadFromAshmem(0, 0)); 781094332d3Sopenharmony_ci eosFlag = this->ReadOnePacket(fpIn_, static_cast<char *>(sharedAddr), bufferInfo->omxBuffer->filledLen); 782094332d3Sopenharmony_ci bufferInfo->omxBuffer->offset = 0; 783094332d3Sopenharmony_ci } 784094332d3Sopenharmony_ci return true; 785094332d3Sopenharmony_ci} 786094332d3Sopenharmony_ci 787094332d3Sopenharmony_ciint32_t CodecHdiDecode::OnEmptyBufferDone(const struct OmxCodecBuffer &buffer) 788094332d3Sopenharmony_ci{ 789094332d3Sopenharmony_ci HDF_LOGI("OnEmptyBufferDone, bufferId [%{public}d]", buffer.bufferId); 790094332d3Sopenharmony_ci unique_lock<mutex> ulk(lockInputBuffers_); 791094332d3Sopenharmony_ci unUsedInBuffers_.push_back(buffer.bufferId); 792094332d3Sopenharmony_ci return HDF_SUCCESS; 793094332d3Sopenharmony_ci} 794094332d3Sopenharmony_ci 795094332d3Sopenharmony_ciint32_t CodecHdiDecode::OnFillBufferDone(const struct OmxCodecBuffer &buffer) 796094332d3Sopenharmony_ci{ 797094332d3Sopenharmony_ci HDF_LOGI("OnFillBufferDone, bufferId [%{public}d]", buffer.bufferId); 798094332d3Sopenharmony_ci if (exit_) { 799094332d3Sopenharmony_ci return HDF_SUCCESS; 800094332d3Sopenharmony_ci } 801094332d3Sopenharmony_ci 802094332d3Sopenharmony_ci auto iter = omxBuffers_.find(buffer.bufferId); 803094332d3Sopenharmony_ci if ((iter == omxBuffers_.end()) || (iter->second == nullptr)) { 804094332d3Sopenharmony_ci return HDF_SUCCESS; 805094332d3Sopenharmony_ci } 806094332d3Sopenharmony_ci count_++; 807094332d3Sopenharmony_ci // read buffer 808094332d3Sopenharmony_ci auto bufferInfo = iter->second; 809094332d3Sopenharmony_ci if (bufferInfo->avSharedPtr != nullptr) { 810094332d3Sopenharmony_ci const void *addr = bufferInfo->avSharedPtr->ReadFromAshmem(buffer.filledLen, buffer.offset); 811094332d3Sopenharmony_ci (void)fwrite(addr, 1, buffer.filledLen, fpOut_); 812094332d3Sopenharmony_ci } else if (bufferInfo->bufferHandle != nullptr && gralloc_ != nullptr) { 813094332d3Sopenharmony_ci gralloc_->Mmap(*bufferInfo->bufferHandle); 814094332d3Sopenharmony_ci (void)fwrite(bufferInfo->bufferHandle->virAddr, 1, buffer.filledLen, fpOut_); 815094332d3Sopenharmony_ci gralloc_->Unmap(*bufferInfo->bufferHandle); 816094332d3Sopenharmony_ci } 817094332d3Sopenharmony_ci 818094332d3Sopenharmony_ci (void)fflush(fpOut_); 819094332d3Sopenharmony_ci if (buffer.flag == OMX_BUFFERFLAG_EOS) { 820094332d3Sopenharmony_ci // end 821094332d3Sopenharmony_ci exit_ = true; 822094332d3Sopenharmony_ci HDF_LOGI("OnFillBufferDone the END coming"); 823094332d3Sopenharmony_ci return HDF_SUCCESS; 824094332d3Sopenharmony_ci } 825094332d3Sopenharmony_ci // call fillthisbuffer again 826094332d3Sopenharmony_ci auto err = client_->FillThisBuffer(*bufferInfo->omxBuffer.get()); 827094332d3Sopenharmony_ci if (err != HDF_SUCCESS) { 828094332d3Sopenharmony_ci HDF_LOGE("%{public}s FillThisBuffer error", __func__); 829094332d3Sopenharmony_ci return HDF_SUCCESS; 830094332d3Sopenharmony_ci } 831094332d3Sopenharmony_ci return HDF_SUCCESS; 832094332d3Sopenharmony_ci} 833094332d3Sopenharmony_ci 834094332d3Sopenharmony_civoid CodecHdiDecode::FreeOutBuffer() 835094332d3Sopenharmony_ci{ 836094332d3Sopenharmony_ci uint32_t port = static_cast<uint32_t>(PortIndex::PORT_INDEX_OUTPUT); 837094332d3Sopenharmony_ci for (auto bufferId : unUsedOutBuffers_) { 838094332d3Sopenharmony_ci HDF_LOGI("FreeOutBuffer, bufferid [%{public}d]", bufferId); 839094332d3Sopenharmony_ci auto iter = omxBuffers_.find(bufferId); 840094332d3Sopenharmony_ci if (iter == omxBuffers_.end()) { 841094332d3Sopenharmony_ci break; 842094332d3Sopenharmony_ci } 843094332d3Sopenharmony_ci auto bufferInfo = iter->second; 844094332d3Sopenharmony_ci auto err = client_->FreeBuffer(port, *bufferInfo->omxBuffer.get()); 845094332d3Sopenharmony_ci if (err != HDF_SUCCESS) { 846094332d3Sopenharmony_ci HDF_LOGE("%{public}s error", __func__); 847094332d3Sopenharmony_ci return; 848094332d3Sopenharmony_ci } 849094332d3Sopenharmony_ci omxBuffers_.erase(iter); 850094332d3Sopenharmony_ci } 851094332d3Sopenharmony_ci} 852094332d3Sopenharmony_ci 853094332d3Sopenharmony_civoid CodecHdiDecode::HandleEventPortSettingsChanged(uint32_t data1, uint32_t data2) 854094332d3Sopenharmony_ci{ 855094332d3Sopenharmony_ci uint32_t port = static_cast<uint32_t>(PortIndex::PORT_INDEX_OUTPUT); 856094332d3Sopenharmony_ci if (data2 == OMX_IndexParamPortDefinition) { 857094332d3Sopenharmony_ci auto err = client_->SendCommand(CODEC_COMMAND_PORT_DISABLE, port, {}); 858094332d3Sopenharmony_ci if (err != HDF_SUCCESS) { 859094332d3Sopenharmony_ci HDF_LOGE("%{public}s error", __func__); 860094332d3Sopenharmony_ci return; 861094332d3Sopenharmony_ci } 862094332d3Sopenharmony_ci FreeOutBuffer(); 863094332d3Sopenharmony_ci err = client_->SendCommand(CODEC_COMMAND_PORT_ENABLE, port, {}); 864094332d3Sopenharmony_ci if (err != HDF_SUCCESS) { 865094332d3Sopenharmony_ci HDF_LOGE("%{public}s error", __func__); 866094332d3Sopenharmony_ci return; 867094332d3Sopenharmony_ci } 868094332d3Sopenharmony_ci UseBufferOnPort(PortIndex::PORT_INDEX_OUTPUT); 869094332d3Sopenharmony_ci FillAllTheBuffer(); 870094332d3Sopenharmony_ci } 871094332d3Sopenharmony_ci} 872094332d3Sopenharmony_ci 873094332d3Sopenharmony_ciint32_t CodecHdiDecode::EventHandler(CodecEventType event, const EventInfo &info) 874094332d3Sopenharmony_ci{ 875094332d3Sopenharmony_ci switch (event) { 876094332d3Sopenharmony_ci case CODEC_EVENT_CMD_COMPLETE: { 877094332d3Sopenharmony_ci CodecCommandType cmd = (CodecCommandType)info.data1; 878094332d3Sopenharmony_ci if (CODEC_COMMAND_STATE_SET == cmd) { 879094332d3Sopenharmony_ci HDF_LOGI("CODEC_COMMAND_STATE_SET reached, status is %{public}d", info.data2); 880094332d3Sopenharmony_ci this->OnStatusChanged(); 881094332d3Sopenharmony_ci } 882094332d3Sopenharmony_ci break; 883094332d3Sopenharmony_ci } 884094332d3Sopenharmony_ci case OMX_EventPortSettingsChanged: { 885094332d3Sopenharmony_ci HDF_LOGI("OMX_EventPortSeetingsChanged reached"); 886094332d3Sopenharmony_ci this->HandleEventPortSettingsChanged(info.data1, info.data2); 887094332d3Sopenharmony_ci } 888094332d3Sopenharmony_ci 889094332d3Sopenharmony_ci default: 890094332d3Sopenharmony_ci break; 891094332d3Sopenharmony_ci } 892094332d3Sopenharmony_ci 893094332d3Sopenharmony_ci return HDF_SUCCESS; 894094332d3Sopenharmony_ci} 895094332d3Sopenharmony_ci 896094332d3Sopenharmony_ciint main(int argc, char *argv[]) 897094332d3Sopenharmony_ci{ 898094332d3Sopenharmony_ci CommandOpt opt; 899094332d3Sopenharmony_ci CommandParse parse; 900094332d3Sopenharmony_ci if (!parse.Parse(argc, argv, opt)) { 901094332d3Sopenharmony_ci return HDF_FAILURE; 902094332d3Sopenharmony_ci } 903094332d3Sopenharmony_ci auto core = std::make_shared<CodecHdiDecode>(); 904094332d3Sopenharmony_ci // Init width, height, input file 905094332d3Sopenharmony_ci if (!core->Init(opt)) { 906094332d3Sopenharmony_ci return HDF_FAILURE; 907094332d3Sopenharmony_ci } 908094332d3Sopenharmony_ci 909094332d3Sopenharmony_ci if (!core->Configure()) { 910094332d3Sopenharmony_ci return HDF_FAILURE; 911094332d3Sopenharmony_ci } 912094332d3Sopenharmony_ci 913094332d3Sopenharmony_ci if (!core->UseBuffers()) { 914094332d3Sopenharmony_ci return HDF_FAILURE; 915094332d3Sopenharmony_ci } 916094332d3Sopenharmony_ci 917094332d3Sopenharmony_ci core->Run(); 918094332d3Sopenharmony_ci core->FreeBuffers(); 919094332d3Sopenharmony_ci core->Release(); 920094332d3Sopenharmony_ci core = nullptr; 921094332d3Sopenharmony_ci}