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