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 
31 using OHOS::HDI::Codec::V3_0::EventInfo;
32 using OHOS::HDI::Codec::V3_0::CodecEventType;
33 using OHOS::HDI::Codec::V3_0::CodecStateType;
34 using OHOS::HDI::Codec::V3_0::CodecCommandType;
35 using OHOS::HDI::Codec::V3_0::CodecStateType;
36 using OHOS::HDI::Codec::V3_0::CODEC_STATE_INVALID;
37 using OHOS::HDI::Codec::V3_0::CODEC_STATE_LOADED;
38 using OHOS::HDI::Codec::V3_0::CODEC_STATE_IDLE;
39 using OHOS::HDI::Codec::V3_0::CODEC_STATE_EXECUTING;
40 using OHOS::HDI::Codec::V3_0::CODEC_COMMAND_STATE_SET;
41 #define FD_SIZE sizeof(int)
42 namespace {
43     constexpr int NAME_LENGTH = 32;
44     constexpr int ROLE_MAX_LEN = 256;
45 }
46 
47 namespace OHOS {
48 namespace Codec {
49 namespace Omx {
OnEvent(OMX_HANDLETYPE component, void *appData, OMX_EVENTTYPE event, uint32_t data1, uint32_t data2, void *eventData)50 OMX_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 
OnEmptyBufferDone(OMX_HANDLETYPE component, void *appData, OMX_BUFFERHEADERTYPE *buffer)61 OMX_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 
OnFillBufferDone(OMX_HANDLETYPE component, void *appData, OMX_BUFFERHEADERTYPE *buffer)71 OMX_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 
81 OMX_CALLBACKTYPE ComponentNode::callbacks_ = {&ComponentNode::OnEvent, &ComponentNode::OnEmptyBufferDone,
82                                               &ComponentNode::OnFillBufferDone};
83 
ComponentNode(const sptr<ICodecCallback> &callbacks, int64_t appData, std::shared_ptr<ComponentMgr> &mgr)84 ComponentNode::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 
~ComponentNode()93 ComponentNode::~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 
OpenHandle(const std::string &name)106 int32_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 
CloseHandle()123 int32_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 
GetComponentVersion(CompVerInfo &verInfo)138 int32_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 
SendCommand(CodecCommandType cmd, uint32_t param, int8_t *cmdData)167 int32_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 
GetParameter(OMX_INDEXTYPE paramIndex, int8_t *param)178 int32_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 
SetParameter(OMX_INDEXTYPE paramIndex, const int8_t *param)188 int32_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 
SetParameterWithBuffer(int32_t index, const std::vector<int8_t>& paramStruct, const OmxCodecBuffer& inBuffer)198 int32_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 
GetConfig(OMX_INDEXTYPE index, int8_t *config)242 int32_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 
SetConfig(OMX_INDEXTYPE index, const int8_t *config)252 int32_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 
GetExtensionIndex(const char *parameterName, uint32_t &index)262 int32_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 
GetState(CodecStateType &state)275 int32_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 
ComponentTunnelRequest(uint32_t port, int32_t omxHandleTypeTunneledComp, uint32_t tunneledPort, OHOS::HDI::Codec::V3_0::CodecTunnelSetupType &tunnelSetup)288 int32_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 
SetCallbacks(const sptr<ICodecCallback> &callbacks, int64_t appData)306 int32_t ComponentNode::SetCallbacks(const sptr<ICodecCallback> &callbacks, int64_t appData)
307 {
308     this->omxCallback_ = callbacks;
309     appData_ = appData;
310     return OMX_ErrorNone;
311 }
312 
UseEglImage(struct OmxCodecBuffer &buffer, uint32_t portIndex, const int8_t *eglImage)313 int32_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 
ComponentRoleEnum(std::vector<uint8_t> &role, uint32_t index)326 int32_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 
ComponentDeInit()345 int32_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 
OnEvent(CodecEventType event, uint32_t data1, uint32_t data2, void *eventData)356 int32_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 
OnEmptyBufferDone(OMX_BUFFERHEADERTYPE *buffer)371 int32_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 
OnFillBufferDone(OMX_BUFFERHEADERTYPE *buffer)388 int32_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 
UseBuffer(uint32_t portIndex, OmxCodecBuffer &buffer)415 int32_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 
AllocateBuffer(uint32_t portIndex, OmxCodecBuffer &buffer)449 int32_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 
FreeBuffer(uint32_t portIndex, const OmxCodecBuffer &buffer)482 int32_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 
EmptyThisBuffer(OmxCodecBuffer &buffer)539 int32_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 
FillThisBuffer(OmxCodecBuffer &buffer)567 int32_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 
UseBufferByType(uint32_t portIndex, OmxCodecBuffer &buffer, sptr<ICodecBuffer> codecBuffer, OMX_BUFFERHEADERTYPE *&bufferHdrType)588 int32_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 
GenerateBufferId()623 uint32_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 
GetBufferInfoByHeader(OMX_BUFFERHEADERTYPE *buffer)636 sptr<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 
GetBufferById(uint32_t bufferId, sptr<ICodecBuffer> &codecBuffer, OMX_BUFFERHEADERTYPE *&bufferHdrType)658 bool 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 
WaitStateChange(CodecStateType objState, CodecStateType &status)683 void 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 
GetBuffCount(uint32_t &inputBuffCount, uint32_t &outputBuffCount)698 void 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 
ReleaseOMXResource()712 void 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 
ReleaseAllBuffer()740 int32_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