1/*
2 * Copyright (c) 2022-2023 Shenzhen Kaihong DID Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * 		http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "component_node.h"
17#include <ashmem.h>
18#include <securec.h>
19#include <unistd.h>
20#include <sys/stat.h>
21#include <hitrace_meter.h>
22#include "codec_log_wrapper.h"
23#include "component_mgr.h"
24#include "icodec_buffer.h"
25#include "sys/mman.h"
26#include "v3_0/codec_ext_types.h"
27#include "codec_component_service.h"
28
29#define AUDIO_CODEC_NAME "OMX.audio"
30
31using OHOS::HDI::Codec::V3_0::EventInfo;
32using OHOS::HDI::Codec::V3_0::CodecEventType;
33using OHOS::HDI::Codec::V3_0::CodecStateType;
34using OHOS::HDI::Codec::V3_0::CodecCommandType;
35using OHOS::HDI::Codec::V3_0::CodecStateType;
36using OHOS::HDI::Codec::V3_0::CODEC_STATE_INVALID;
37using OHOS::HDI::Codec::V3_0::CODEC_STATE_LOADED;
38using OHOS::HDI::Codec::V3_0::CODEC_STATE_IDLE;
39using OHOS::HDI::Codec::V3_0::CODEC_STATE_EXECUTING;
40using OHOS::HDI::Codec::V3_0::CODEC_COMMAND_STATE_SET;
41#define FD_SIZE sizeof(int)
42namespace {
43    constexpr int NAME_LENGTH = 32;
44    constexpr int ROLE_MAX_LEN = 256;
45}
46
47namespace OHOS {
48namespace Codec {
49namespace Omx {
50OMX_ERRORTYPE ComponentNode::OnEvent(OMX_HANDLETYPE component, void *appData, OMX_EVENTTYPE event, uint32_t data1,
51                                     uint32_t data2, void *eventData)
52{
53    ComponentNode *node = static_cast<ComponentNode *>(appData);
54    (void)component;
55    if (node != nullptr) {
56        node->OnEvent(static_cast<CodecEventType>(event), data1, data2, eventData);
57    }
58    return OMX_ErrorNone;
59}
60
61OMX_ERRORTYPE ComponentNode::OnEmptyBufferDone(OMX_HANDLETYPE component, void *appData, OMX_BUFFERHEADERTYPE *buffer)
62{
63    ComponentNode *node = static_cast<ComponentNode *>(appData);
64    (void)component;
65    if (node != nullptr) {
66        node->OnEmptyBufferDone(buffer);
67    }
68    return OMX_ErrorNone;
69}
70
71OMX_ERRORTYPE ComponentNode::OnFillBufferDone(OMX_HANDLETYPE component, void *appData, OMX_BUFFERHEADERTYPE *buffer)
72{
73    ComponentNode *node = static_cast<ComponentNode *>(appData);
74    (void)component;
75    if (node != nullptr) {
76        node->OnFillBufferDone(buffer);
77    }
78    return OMX_ErrorNone;
79}
80
81OMX_CALLBACKTYPE ComponentNode::callbacks_ = {&ComponentNode::OnEvent, &ComponentNode::OnEmptyBufferDone,
82                                              &ComponentNode::OnFillBufferDone};
83
84ComponentNode::ComponentNode(const sptr<ICodecCallback> &callbacks, int64_t appData, std::shared_ptr<ComponentMgr> &mgr)
85    : comp_(nullptr),
86      omxCallback_(callbacks),
87      appData_(appData),
88      bufferIdCount_(0),
89      mgr_(mgr)
90{
91}
92
93ComponentNode::~ComponentNode()
94{
95    std::unique_lock<std::shared_mutex> lk(mapMutex_);
96    omxCallback_ = nullptr;
97    bufferHeaderPortMap_.clear();
98    codecBufferMap_.clear();
99    bufferHeaderMap_.clear();
100    portIndexMap_.clear();
101    bufferIdCount_ = 0;
102    comp_ = nullptr;
103    mgr_ = nullptr;
104}
105
106int32_t ComponentNode::OpenHandle(const std::string &name)
107{
108    if (comp_ != nullptr) {
109        return HDF_SUCCESS;
110    }
111
112    OMX_COMPONENTTYPE *comp = nullptr;
113    auto err = mgr_->CreateComponentInstance(name.c_str(), &callbacks_, this, &comp);
114    if (err != OMX_ErrorNone) {
115        CODEC_LOGE("CreateComponentInstance err = %{public}x ", err);
116        return err;
117    }
118    this->comp_ = (OMX_HANDLETYPE)comp;
119    compName_ = name;
120    return HDF_SUCCESS;
121}
122
123int32_t ComponentNode::CloseHandle()
124{
125    if (comp_ == nullptr) {
126        CODEC_LOGE("comp_ is null");
127        return HDF_FAILURE;
128    }
129
130    auto err = mgr_->DeleteComponentInstance(reinterpret_cast<OMX_COMPONENTTYPE *>(comp_));
131    if (err != OMX_ErrorNone) {
132        CODEC_LOGE("DeleteComponentInstance err = %{public}x ", err);
133        return err;
134    }
135    return HDF_SUCCESS;
136}
137
138int32_t ComponentNode::GetComponentVersion(CompVerInfo &verInfo)
139{
140    CHECK_AND_RETURN_RET_LOG(comp_ != nullptr, OMX_ErrorInvalidComponent, "comp_ is null");
141    char name[NAME_LENGTH] = {0};
142    OMX_UUIDTYPE uuid = {0};
143    OMX_VERSIONTYPE compVersion = {.nVersion = 0};
144    OMX_VERSIONTYPE sepcVersion = {.nVersion = 0};
145    int32_t err = OMX_GetComponentVersion(comp_, name, &compVersion, &sepcVersion, &uuid);
146    if (err != OMX_ErrorNone) {
147        CODEC_LOGE("OMX_GetComponentVersion err = %{public}x ", err);
148        return err;
149    }
150
151    verInfo.compName = name;
152    verInfo.compUUID.insert(verInfo.compUUID.end(), uuid, uuid + sizeof(OMX_UUIDTYPE));
153    err = memcpy_s(&verInfo.compVersion, sizeof(verInfo.compVersion), &compVersion, sizeof(sepcVersion));
154    if (err != HDF_SUCCESS) {
155        CODEC_LOGE("memset_s return err [%{public}d].", err);
156        return err;
157    }
158
159    err = memcpy_s(&verInfo.specVersion, sizeof(verInfo.specVersion), &sepcVersion, sizeof(sepcVersion));
160    if (err != HDF_SUCCESS) {
161        CODEC_LOGE("memset_s return err [%{public}d].", err);
162        return err;
163    }
164    return err;
165}
166
167int32_t ComponentNode::SendCommand(CodecCommandType cmd, uint32_t param, int8_t *cmdData)
168{
169    CHECK_AND_RETURN_RET_LOG(comp_ != nullptr, OMX_ErrorInvalidComponent, "comp_ is null");
170    OMX_COMMANDTYPE omxCmd = static_cast<OMX_COMMANDTYPE>(cmd);
171    auto err = OMX_SendCommand(comp_, omxCmd, param, cmdData);
172    if (err != OMX_ErrorNone) {
173        CODEC_LOGE("OMX_SendCommand err = %{public}x ", err);
174    }
175    return err;
176}
177
178int32_t ComponentNode::GetParameter(OMX_INDEXTYPE paramIndex, int8_t *param)
179{
180    CHECK_AND_RETURN_RET_LOG(comp_ != nullptr, OMX_ErrorInvalidComponent, "comp_ is null");
181    auto err = OMX_GetParameter(comp_, paramIndex, param);
182    if (err != OMX_ErrorNone) {
183        CODEC_LOGE("OMX_GetParameter err = %{public}x ", err);
184    }
185    return err;
186}
187
188int32_t ComponentNode::SetParameter(OMX_INDEXTYPE paramIndex, const int8_t *param)
189{
190    CHECK_AND_RETURN_RET_LOG(comp_ != nullptr, OMX_ErrorInvalidComponent, "comp_ is null");
191    auto err = OMX_SetParameter(comp_, paramIndex, const_cast<int8_t *>(param));
192    if (err != OMX_ErrorNone) {
193        CODEC_LOGE("OMX_SetParameter err = %{public}x ", err);
194    }
195    return err;
196}
197
198int32_t ComponentNode::SetParameterWithBuffer(int32_t index, const std::vector<int8_t>& paramStruct,
199    const OmxCodecBuffer& inBuffer)
200{
201    CHECK_AND_RETURN_RET_LOG(comp_ != nullptr, OMX_ErrorInvalidComponent, "comp_ is null");
202    if (index != HDI::Codec::V3_0::Codec_IndexParamOverlayBuffer) {
203        return OMX_ErrorNotImplemented;
204    }
205    if (paramStruct.size() != sizeof(HDI::Codec::V3_0::CodecParamOverlay)) {
206        return OMX_ErrorBadParameter;
207    }
208    if (inBuffer.bufferhandle == nullptr) {
209        CODEC_LOGE("null bufferhandle");
210        return OMX_ErrorBadParameter;
211    }
212    BufferHandle* handle = inBuffer.bufferhandle->GetBufferHandle();
213    if (handle == nullptr) {
214        CODEC_LOGE("null bufferhandle");
215        return OMX_ErrorBadParameter;
216    }
217    sptr<OHOS::HDI::Display::Buffer::V1_0::IMapper> mapper = HDI::Codec::V3_0::GetMapperService();
218    if (mapper != nullptr) {
219        mapper->Mmap(inBuffer.bufferhandle);
220    }
221    auto paramSrc = reinterpret_cast<const HDI::Codec::V3_0::CodecParamOverlay *>(paramStruct.data());
222    CodecParamOverlayBuffer paramDst {
223        .size = sizeof(CodecParamOverlayBuffer),
224        .enable = paramSrc->enable,
225        .dstX = paramSrc->dstX,
226        .dstY = paramSrc->dstY,
227        .dstW = paramSrc->dstW,
228        .dstH = paramSrc->dstH,
229        .bufferHandle = handle,
230    };
231    auto err = OMX_SetParameter(comp_, static_cast<OMX_INDEXTYPE>(OMX_IndexParamOverlayBuffer),
232        reinterpret_cast<int8_t *>(&paramDst));
233    if (err != OMX_ErrorNone) {
234        CODEC_LOGE("OMX_SetParameter err = %{public}x ", err);
235    }
236    if (mapper != nullptr) {
237        mapper->Unmap(inBuffer.bufferhandle);
238    }
239    return err;
240}
241
242int32_t ComponentNode::GetConfig(OMX_INDEXTYPE index, int8_t *config)
243{
244    CHECK_AND_RETURN_RET_LOG(comp_ != nullptr, OMX_ErrorInvalidComponent, "comp_ is null");
245    auto err = OMX_GetConfig(comp_, index, config);
246    if (err != OMX_ErrorNone) {
247        CODEC_LOGE("OMX_GetConfig err = %{public}x ", err);
248    }
249    return err;
250}
251
252int32_t ComponentNode::SetConfig(OMX_INDEXTYPE index, const int8_t *config)
253{
254    CHECK_AND_RETURN_RET_LOG(comp_ != nullptr, OMX_ErrorInvalidComponent, "comp_ is null");
255    auto err = OMX_SetConfig(comp_, index, const_cast<int8_t *>(config));
256    if (err != OMX_ErrorNone) {
257        CODEC_LOGE("OMX_SetConfig err = %{public}x ", err);
258    }
259    return err;
260}
261
262int32_t ComponentNode::GetExtensionIndex(const char *parameterName, uint32_t &index)
263{
264    CHECK_AND_RETURN_RET_LOG(comp_ != nullptr, OMX_ErrorInvalidComponent, "comp_ is null");
265    OMX_INDEXTYPE indexType = OMX_IndexComponentStartUnused;
266    auto err = OMX_GetExtensionIndex(comp_, const_cast<char *>(parameterName), &indexType);
267    if (err != OMX_ErrorNone) {
268        CODEC_LOGE("OMX_GetExtensionIndex ret value[%{public}x]", err);
269        return err;
270    }
271    index = indexType;
272    return err;
273}
274
275int32_t ComponentNode::GetState(CodecStateType &state)
276{
277    CHECK_AND_RETURN_RET_LOG(comp_ != nullptr, OMX_ErrorInvalidComponent, "comp_ is null");
278    OMX_STATETYPE status = OMX_StateInvalid;
279    auto err = OMX_GetState(comp_, &status);
280    if (err != OMX_ErrorNone) {
281        CODEC_LOGE("OMX_GetState ret value[%{public}x]", err);
282        return err;
283    }
284    state = static_cast<CodecStateType>(status);
285    return err;
286}
287
288int32_t ComponentNode::ComponentTunnelRequest(uint32_t port, int32_t omxHandleTypeTunneledComp, uint32_t tunneledPort,
289                                              OHOS::HDI::Codec::V3_0::CodecTunnelSetupType &tunnelSetup)
290{
291    CHECK_AND_RETURN_RET_LOG(comp_ != nullptr, OMX_ErrorInvalidComponent, "comp_ is null");
292    OMX_COMPONENTTYPE *comType = static_cast<OMX_COMPONENTTYPE *>(comp_);
293    unsigned long tunneledComp = static_cast<unsigned long>(omxHandleTypeTunneledComp);
294    if (comType->ComponentTunnelRequest == nullptr) {
295        CODEC_LOGE("The requested function is not implemented.");
296        return OMX_ErrorNotImplemented;
297    }
298    auto err = comType->ComponentTunnelRequest(comp_, port, reinterpret_cast<OMX_HANDLETYPE>(tunneledComp),
299        tunneledPort, reinterpret_cast<OMX_TUNNELSETUPTYPE *>(&tunnelSetup));
300    if (err != OMX_ErrorNone) {
301        CODEC_LOGE("ComponentTunnelRequest err = %{public}x ", err);
302    }
303    return err;
304}
305
306int32_t ComponentNode::SetCallbacks(const sptr<ICodecCallback> &callbacks, int64_t appData)
307{
308    this->omxCallback_ = callbacks;
309    appData_ = appData;
310    return OMX_ErrorNone;
311}
312
313int32_t ComponentNode::UseEglImage(struct OmxCodecBuffer &buffer, uint32_t portIndex, const int8_t *eglImage)
314{
315    CHECK_AND_RETURN_RET_LOG(comp_ != nullptr, OMX_ErrorInvalidComponent, "comp_ is null");
316    OMX_BUFFERHEADERTYPE *pBufferHdrType = nullptr;
317    auto err = OMX_UseEGLImage(comp_, &pBufferHdrType, portIndex, 0, const_cast<int8_t *>(eglImage));
318    if (err != OMX_ErrorNone) {
319        CODEC_LOGE("OMX_UseEGLImage error[0x%{public}x]", err);
320        return err;
321    }
322    (void)buffer;
323    return OMX_ErrorNotImplemented;
324}
325
326int32_t ComponentNode::ComponentRoleEnum(std::vector<uint8_t> &role, uint32_t index)
327{
328    CHECK_AND_RETURN_RET_LOG(comp_ != nullptr, OMX_ErrorInvalidComponent, "comp_ is null");
329    CHECK_AND_RETURN_RET_LOG(index < ROLE_MAX_LEN, HDF_ERR_INVALID_PARAM, "index is too large");
330    uint8_t omxRole[ROLE_MAX_LEN] = {0};
331    OMX_COMPONENTTYPE *comType = static_cast<OMX_COMPONENTTYPE *>(comp_);
332    if (comType->ComponentRoleEnum == nullptr) {
333        CODEC_LOGE("The requested function is not implemented.");
334        return OMX_ErrorNotImplemented;
335    }
336    int32_t err = comType->ComponentRoleEnum(comp_, omxRole, index);
337    if (err != OMX_ErrorNone) {
338        CODEC_LOGE("ComponentRoleEnum ret err [0x%{public}x] ", err);
339        return err;
340    }
341    role.insert(role.end(), omxRole, omxRole + strlen(reinterpret_cast<const char *>(omxRole)));
342    return OMX_ErrorNone;
343}
344
345int32_t ComponentNode::ComponentDeInit()
346{
347    CHECK_AND_RETURN_RET_LOG(comp_ != nullptr, OMX_ErrorInvalidComponent, "comp_ is null");
348    OMX_COMPONENTTYPE *comType = static_cast<OMX_COMPONENTTYPE *>(comp_);
349    auto err = comType->ComponentDeInit(comp_);
350    if (err != OMX_ErrorNone) {
351        CODEC_LOGE("ComponentDeInit err = %{public}x ", err);
352    }
353    return err;
354}
355
356int32_t ComponentNode::OnEvent(CodecEventType event, uint32_t data1, uint32_t data2, void *eventData)
357{
358    CODEC_LOGD("eventType: [%{public}d], data1: [%{public}x], data2: [%{public}x]", event, data1, data2);
359    if (omxCallback_ == nullptr) {
360        CODEC_LOGE("omxCallback_ is null");
361        return OMX_ErrorNone;
362    }
363    (void)eventData;
364    EventInfo info = {.appData = appData_, .data1 = data1, .data2 = data2};
365    HITRACE_METER_NAME(HITRACE_TAG_HDF, "HDFCodecOnEvent");
366    (void)omxCallback_->EventHandler(event, info);
367
368    return OMX_ErrorNone;
369}
370
371int32_t ComponentNode::OnEmptyBufferDone(OMX_BUFFERHEADERTYPE *buffer)
372{
373    if ((omxCallback_ == nullptr) || (buffer == nullptr)) {
374        CODEC_LOGE("omxCallback_ or buffer is null");
375        return OMX_ErrorNone;
376    }
377    sptr<ICodecBuffer> codecBuffer = GetBufferInfoByHeader(buffer);
378    if (codecBuffer == nullptr || codecBuffer->EmptyOmxBufferDone(*buffer) != HDF_SUCCESS) {
379        CODEC_LOGE("codecBuffer is null or EmptyOmxBufferDone error");
380        return OMX_ErrorNone;
381    }
382    OmxCodecBuffer &codecOmxBuffer = codecBuffer->GetCodecBuffer();
383    HITRACE_METER_NAME(HITRACE_TAG_HDF, "HDFCodecOnEmptyBufferDone");
384    (void)omxCallback_->EmptyBufferDone(appData_, codecOmxBuffer);
385    return OMX_ErrorNone;
386}
387
388int32_t ComponentNode::OnFillBufferDone(OMX_BUFFERHEADERTYPE *buffer)
389{
390    if ((omxCallback_ == nullptr) || (buffer == nullptr)) {
391        CODEC_LOGE("omxCallback_ or buffer is null");
392        return OMX_ErrorNone;
393    }
394
395    sptr<ICodecBuffer> codecBuffer = GetBufferInfoByHeader(buffer);
396    if (codecBuffer == nullptr || codecBuffer->FillOmxBufferDone(*buffer) != HDF_SUCCESS) {
397        CODEC_LOGE("codecBuffer is null or EmptyOmxBufferDone error");
398        return OMX_ErrorNone;
399    }
400
401    struct OmxCodecBuffer &codecOmxBuffer = codecBuffer->GetCodecBuffer();
402    HITRACE_METER_NAME(HITRACE_TAG_HDF, "HDFCodecOnFillBufferDone");
403    auto appPrivate = static_cast<OMXBufferAppPrivateData *>(buffer->pAppPrivate);
404    if (appPrivate != nullptr && appPrivate->param != nullptr &&
405        appPrivate->sizeOfParam < 1024) { // 1024: to protect from taint data
406        codecOmxBuffer.alongParam.resize(appPrivate->sizeOfParam);
407        std::copy(static_cast<uint8_t*>(appPrivate->param),
408                  static_cast<uint8_t*>(appPrivate->param) + appPrivate->sizeOfParam,
409                  codecOmxBuffer.alongParam.begin());
410    }
411    (void)omxCallback_->FillBufferDone(appData_, codecOmxBuffer);
412    return OMX_ErrorNone;
413}
414
415int32_t ComponentNode::UseBuffer(uint32_t portIndex, OmxCodecBuffer &buffer)
416{
417    CHECK_AND_RETURN_RET_LOG(comp_ != nullptr, OMX_ErrorInvalidComponent, "comp_ is null");
418
419    int32_t err = OMX_ErrorBadParameter;
420    sptr<ICodecBuffer> codecBuffer = sptr<ICodecBuffer>();
421    if (compName_.find(AUDIO_CODEC_NAME) != std::string::npos) {
422        codecBuffer = sptr<ICodecBuffer>(new ICodecBuffer(buffer));
423    } else {
424        codecBuffer = ICodecBuffer::CreateCodeBuffer(buffer);
425    }
426    CHECK_AND_RETURN_RET_LOG(codecBuffer != nullptr, OMX_ErrorInvalidComponent, "codecBuffer is null");
427
428    OMX_BUFFERHEADERTYPE *bufferHdrType = nullptr;
429    err = UseBufferByType(portIndex, buffer, codecBuffer, bufferHdrType);
430    if (err != OMX_ErrorNone) {
431        CODEC_LOGE("type [%{public}d] OMX_AllocateBuffer or OMX_UseBuffer ret = [%{public}x]", buffer.bufferType, err);
432        codecBuffer = nullptr;
433        return err;
434    }
435
436    uint32_t bufferId = GenerateBufferId();
437    buffer.bufferId = bufferId;
438    codecBuffer->SetBufferId(bufferId);
439    {
440        std::unique_lock<std::shared_mutex> lk(mapMutex_);
441        codecBufferMap_.emplace(std::make_pair(bufferId, codecBuffer));
442        bufferHeaderMap_.emplace(std::make_pair(bufferHdrType, bufferId));
443        bufferHeaderPortMap_.emplace(std::make_pair(bufferHdrType, portIndex));
444        portIndexMap_.emplace(std::make_pair(bufferHdrType, portIndex));
445    }
446    return err;
447}
448
449int32_t ComponentNode::AllocateBuffer(uint32_t portIndex, OmxCodecBuffer &buffer)
450{
451    CHECK_AND_RETURN_RET_LOG(comp_ != nullptr, OMX_ErrorInvalidComponent, "comp_ is null");
452    OMX_BUFFERHEADERTYPE *bufferHdrType = 0;
453    OMXBufferAppPrivateData priv{};
454    int32_t err = OMX_AllocateBuffer(static_cast<OMX_HANDLETYPE>(comp_),
455                                     &bufferHdrType, portIndex, &priv, buffer.allocLen);
456    if (err != OMX_ErrorNone) {
457        CODEC_LOGE("OMX_AllocateBuffer error, err = %{public}x", err);
458        return err;
459    }
460
461    buffer.allocLen = bufferHdrType->nAllocLen;
462    sptr<ICodecBuffer> codecBuffer = ICodecBuffer::AllocateCodecBuffer(buffer, *bufferHdrType);
463    if (codecBuffer == nullptr) {
464        CODEC_LOGE("codecBuffer is null");
465        (void)OMX_FreeBuffer(static_cast<OMX_HANDLETYPE>(comp_), portIndex, bufferHdrType);
466        return OMX_ErrorInvalidComponent;
467    }
468    bufferHdrType->pAppPrivate = nullptr;
469    uint32_t bufferId = GenerateBufferId();
470    buffer.bufferId = bufferId;
471    codecBuffer->SetBufferId(bufferId);
472    {
473        std::unique_lock<std::shared_mutex> lk(mapMutex_);
474        codecBufferMap_.emplace(std::make_pair(bufferId, codecBuffer));
475        bufferHeaderMap_.emplace(std::make_pair(bufferHdrType, bufferId));
476        bufferHeaderPortMap_.emplace(std::make_pair(bufferHdrType, portIndex));
477        portIndexMap_.emplace(std::make_pair(bufferHdrType, portIndex));
478    }
479    return OMX_ErrorNone;
480}
481
482int32_t ComponentNode::FreeBuffer(uint32_t portIndex, const OmxCodecBuffer &buffer)
483{
484    CHECK_AND_RETURN_RET_LOG(comp_ != nullptr, OMX_ErrorInvalidComponent, "comp_ is null");
485    int32_t err = OMX_ErrorBadParameter;
486    sptr<ICodecBuffer> codecBufer = sptr<ICodecBuffer>();
487    OMX_BUFFERHEADERTYPE *bufferHdrType = nullptr;
488    if (!GetBufferById(buffer.bufferId, codecBufer, bufferHdrType)) {
489        CODEC_LOGE(" GetBufferById return false");
490        return err;
491    }
492
493    err = OMX_FreeBuffer(static_cast<OMX_HANDLETYPE>(comp_), portIndex, bufferHdrType);
494    if (err != OMX_ErrorNone) {
495        CODEC_LOGE("OMX_FreeBuffer err [%{public}x]", err);
496        return err;
497    }
498
499    {
500        std::unique_lock<std::shared_mutex> lk(mapMutex_);
501        auto iterOmxBuffer = bufferHeaderMap_.begin();
502        while (iterOmxBuffer != bufferHeaderMap_.end()) {
503            if (iterOmxBuffer->first == bufferHdrType) {
504                bufferHeaderMap_.erase(iterOmxBuffer);
505                break;
506            }
507            iterOmxBuffer++;
508        }
509
510        iterOmxBuffer = bufferHeaderPortMap_.begin();
511        while (iterOmxBuffer != bufferHeaderPortMap_.end()) {
512            if (iterOmxBuffer->first == bufferHdrType) {
513                bufferHeaderPortMap_.erase(iterOmxBuffer);
514                break;
515            }
516            iterOmxBuffer++;
517        }
518
519        auto iter = codecBufferMap_.find(buffer.bufferId);
520        if (iter != codecBufferMap_.end()) {
521            codecBufferMap_.erase(iter);
522        }
523    }
524
525    (void)codecBufer->FreeBuffer(const_cast<OmxCodecBuffer &>(buffer));
526
527    for (auto it = audioBuffer_.begin(); it != audioBuffer_.end(); it++) {
528        if (it->first == nullptr) {
529            continue;
530        }
531        if (::munmap(it->first, static_cast<size_t>(it->second)) != 0) {
532            CODEC_LOGW("Error munmap");
533        }
534    }
535    audioBuffer_.clear();
536    return err;
537}
538
539int32_t ComponentNode::EmptyThisBuffer(OmxCodecBuffer &buffer)
540{
541    CHECK_AND_RETURN_RET_LOG(comp_ != nullptr, OMX_ErrorInvalidComponent, "comp_ is null");
542    int32_t err = OMX_ErrorBadParameter;
543    OMX_BUFFERHEADERTYPE *bufferHdrType = nullptr;
544    sptr<ICodecBuffer> codecBuffer = sptr<ICodecBuffer>();
545    if (!GetBufferById(buffer.bufferId, codecBuffer, bufferHdrType)) {
546        CODEC_LOGE(" GetBufferById return false");
547        return err;
548    }
549    err = codecBuffer->EmptyOmxBuffer(buffer, *bufferHdrType);
550    if (err != HDF_SUCCESS) {
551        CODEC_LOGE("EmptyOmxBuffer err [%{public}d]", err);
552        return err;
553    }
554    bufferHdrType->pAppPrivate = nullptr;
555    OMXBufferAppPrivateData privateData{};
556    if (buffer.bufferType == CODEC_BUFFER_TYPE_DYNAMIC_HANDLE && (!buffer.alongParam.empty())) {
557        privateData.sizeOfParam = static_cast<uint32_t>(buffer.alongParam.size());
558        privateData.param = static_cast<void *>(buffer.alongParam.data());
559        bufferHdrType->pAppPrivate = static_cast<void *>(&privateData);
560    }
561
562    err = OMX_EmptyThisBuffer(static_cast<OMX_HANDLETYPE>(comp_), bufferHdrType);
563    bufferHdrType->pAppPrivate = nullptr;
564    return err;
565}
566
567int32_t ComponentNode::FillThisBuffer(OmxCodecBuffer &buffer)
568{
569    CHECK_AND_RETURN_RET_LOG(comp_ != nullptr, OMX_ErrorInvalidComponent, "comp_ is null");
570    int32_t err = OMX_ErrorBadParameter;
571    OMX_BUFFERHEADERTYPE *bufferHdrType = nullptr;
572    sptr<ICodecBuffer> codecBuffer = sptr<ICodecBuffer>();
573    if (!GetBufferById(buffer.bufferId, codecBuffer, bufferHdrType)) {
574        CODEC_LOGE("GetBufferById return false");
575        return err;
576    }
577
578    err = codecBuffer->FillOmxBuffer(buffer, *bufferHdrType);
579    if (err != HDF_SUCCESS) {
580        CODEC_LOGE("FillOmxBuffer err [%{public}d]", err);
581        return err;
582    }
583
584    err = OMX_FillThisBuffer(static_cast<OMX_HANDLETYPE>(comp_), bufferHdrType);
585    return err;
586}
587
588int32_t ComponentNode::UseBufferByType(uint32_t portIndex, OmxCodecBuffer &buffer,
589    sptr<ICodecBuffer> codecBuffer, OMX_BUFFERHEADERTYPE *&bufferHdrType)
590{
591    int32_t err = OMX_ErrorUndefined;
592    switch (buffer.bufferType) {
593        case CODEC_BUFFER_TYPE_AVSHARE_MEM_FD: {
594            if (compName_.find(AUDIO_CODEC_NAME) != std::string::npos) {
595                void *addr = ::mmap(nullptr, static_cast<size_t>(buffer.allocLen),
596                    static_cast<int>(PROT_READ | PROT_WRITE), MAP_SHARED, buffer.fd, 0);
597                CHECK_AND_RETURN_RET_LOG(addr != nullptr, OMX_ErrorBadParameter, "addr is null");
598                err = OMX_UseBuffer(static_cast<OMX_HANDLETYPE>(comp_), &bufferHdrType, portIndex, 0, buffer.allocLen,
599                    reinterpret_cast<uint8_t *>(addr));
600                audioBuffer_.push_back({addr, buffer.allocLen});
601                break;
602            }
603            err = OMX_AllocateBuffer(static_cast<OMX_HANDLETYPE>(comp_), &bufferHdrType, portIndex, 0,
604                buffer.allocLen);
605            break;
606        }
607        case CODEC_BUFFER_TYPE_HANDLE:
608        case CODEC_BUFFER_TYPE_DYNAMIC_HANDLE:
609            err = OMX_UseBuffer(static_cast<OMX_HANDLETYPE>(comp_), &bufferHdrType, portIndex, 0, buffer.allocLen,
610                codecBuffer->GetBuffer());
611            break;
612        case CODEC_BUFFER_TYPE_DMA_MEM_FD: {
613            err = OMX_UseBuffer(static_cast<OMX_HANDLETYPE>(comp_), &bufferHdrType, portIndex, 0, 0,
614                reinterpret_cast<uint8_t *>(&buffer.fd));
615            break;
616        }
617        default:
618            break;
619    }
620    return err;
621}
622
623uint32_t ComponentNode::GenerateBufferId()
624{
625    std::unique_lock<std::shared_mutex> lk(mapMutex_);
626    uint32_t bufferId = 0;
627    do {
628        if (++bufferIdCount_ == 0) {
629            ++bufferIdCount_;
630        }
631        bufferId = bufferIdCount_;
632    } while (codecBufferMap_.find(bufferId) != codecBufferMap_.end());
633    return bufferId;
634}
635
636sptr<ICodecBuffer> ComponentNode::GetBufferInfoByHeader(OMX_BUFFERHEADERTYPE *buffer)
637{
638    if (buffer == nullptr) {
639        CODEC_LOGE("Buffer is null");
640        return sptr<ICodecBuffer>();
641    }
642    std::shared_lock<std::shared_mutex> lk(mapMutex_);
643    auto iterHead = bufferHeaderMap_.find(buffer);
644    if (iterHead == bufferHeaderMap_.end()) {
645        CODEC_LOGE("Can not find bufferID");
646        return sptr<ICodecBuffer>();
647    }
648
649    uint32_t bufferId = iterHead->second;
650    auto iter = codecBufferMap_.find(bufferId);
651    if (iter == codecBufferMap_.end()) {
652        CODEC_LOGE("Can not find bufferInfo by bufferId = %{public}d", bufferId);
653        return sptr<ICodecBuffer>();
654    }
655    return iter->second;
656}
657
658bool ComponentNode::GetBufferById(uint32_t bufferId, sptr<ICodecBuffer> &codecBuffer,
659                                  OMX_BUFFERHEADERTYPE *&bufferHdrType)
660{
661    std::shared_lock<std::shared_mutex> lk(mapMutex_);
662    auto iter = codecBufferMap_.find(bufferId);
663    if ((iter == codecBufferMap_.end()) || (iter->second == nullptr)) {
664        CODEC_LOGE("Can not find bufferIndo by bufferID [%{public}d]", bufferId);
665        return false;
666    }
667
668    auto iterHead = bufferHeaderMap_.begin();
669    for (; iterHead != bufferHeaderMap_.end(); iterHead++) {
670        if (iterHead->second == bufferId) {
671            break;
672        }
673    }
674    if ((iterHead == bufferHeaderMap_.end()) || (iterHead->first == nullptr)) {
675        CODEC_LOGE("Can not find bufferHeaderType by bufferID [%{public}d] or iterHead->first is null", bufferId);
676        return false;
677    }
678    bufferHdrType = iterHead->first;
679    codecBuffer = iter->second;
680    return true;
681}
682
683void ComponentNode::WaitStateChange(CodecStateType objState, CodecStateType &status)
684{
685    int32_t ret;
686    uint32_t count = 0;
687    while (status != objState && count < maxStateWaitCount) {
688        usleep(maxStateWaitTime);
689        ret = GetState(status);
690        if (ret != HDF_SUCCESS) {
691            HDF_LOGE("%{public}s: GetState error [%{public}x]", __func__, ret);
692            return;
693        }
694        count++;
695    }
696}
697
698void ComponentNode::GetBuffCount(uint32_t &inputBuffCount, uint32_t &outputBuffCount)
699{
700    std::unique_lock<std::shared_mutex> lk(mapMutex_);
701    auto iter = portIndexMap_.begin();
702    while (iter != portIndexMap_.end()) {
703        if (iter->second == 0) {
704            inputBuffCount++;
705        } else {
706            outputBuffCount++;
707        }
708        iter++;
709    }
710}
711
712void ComponentNode::ReleaseOMXResource()
713{
714    std::shared_lock<std::shared_mutex> lk(mapMutex_);
715    if (codecBufferMap_.size() == 0) {
716        return;
717    }
718    CodecStateType status = CODEC_STATE_INVALID;
719    int32_t ret = GetState(status);
720    if (ret != HDF_SUCCESS) {
721        HDF_LOGE("ReleaseOMXResource GetState error [%{public}x]", ret);
722        return;
723    }
724    if (status == CODEC_STATE_EXECUTING) {
725        SendCommand(CODEC_COMMAND_STATE_SET, CODEC_STATE_IDLE, NULL);
726        WaitStateChange(CODEC_STATE_IDLE, status);
727    }
728    if (status == CODEC_STATE_IDLE) {
729        SendCommand(CODEC_COMMAND_STATE_SET, CODEC_STATE_LOADED, NULL);
730        ret = ReleaseAllBuffer();
731        if (ret != HDF_SUCCESS) {
732            HDF_LOGE("ReleaseAllBuffer err [%{public}x]", ret);
733            return;
734        }
735        WaitStateChange(CODEC_STATE_LOADED, status);
736    }
737    HDF_LOGI("%{public}s: Release OMX Resource success!", __func__);
738}
739
740int32_t ComponentNode::ReleaseAllBuffer()
741{
742    auto iter = bufferHeaderMap_.begin();
743    for (; iter != bufferHeaderMap_.end(); iter++) {
744        OMX_BUFFERHEADERTYPE *bufferHdrType = iter->first;
745        uint32_t protIndex = bufferHeaderPortMap_.find(bufferHdrType)->second;
746        auto ret = OMX_FreeBuffer((OMX_HANDLETYPE)comp_, protIndex, bufferHdrType);
747        if (ret != OMX_ErrorNone) {
748            HDF_LOGE("OMX_FreeBuffer err [%{public}x]", ret);
749            return ret;
750        }
751    }
752    HDF_LOGI("Release OMXBuffer and CodecBuffer success!");
753    return HDF_SUCCESS;
754}
755}  // namespace Omx
756}  // namespace Codec
757}  // namespace OHOS
758