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