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}