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     return err;
528 }
529 
EmptyThisBuffer(OmxCodecBuffer & buffer)530 int32_t ComponentNode::EmptyThisBuffer(OmxCodecBuffer &buffer)
531 {
532     CHECK_AND_RETURN_RET_LOG(comp_ != nullptr, OMX_ErrorInvalidComponent, "comp_ is null");
533     int32_t err = OMX_ErrorBadParameter;
534     OMX_BUFFERHEADERTYPE *bufferHdrType = nullptr;
535     sptr<ICodecBuffer> codecBuffer = sptr<ICodecBuffer>();
536     if (!GetBufferById(buffer.bufferId, codecBuffer, bufferHdrType)) {
537         CODEC_LOGE(" GetBufferById return false");
538         return err;
539     }
540     err = codecBuffer->EmptyOmxBuffer(buffer, *bufferHdrType);
541     if (err != HDF_SUCCESS) {
542         CODEC_LOGE("EmptyOmxBuffer err [%{public}d]", err);
543         return err;
544     }
545     bufferHdrType->pAppPrivate = nullptr;
546     OMXBufferAppPrivateData privateData{};
547     if (buffer.bufferType == CODEC_BUFFER_TYPE_DYNAMIC_HANDLE && (!buffer.alongParam.empty())) {
548         privateData.sizeOfParam = static_cast<uint32_t>(buffer.alongParam.size());
549         privateData.param = static_cast<void *>(buffer.alongParam.data());
550         bufferHdrType->pAppPrivate = static_cast<void *>(&privateData);
551     }
552 
553     err = OMX_EmptyThisBuffer(static_cast<OMX_HANDLETYPE>(comp_), bufferHdrType);
554     bufferHdrType->pAppPrivate = nullptr;
555     return err;
556 }
557 
FillThisBuffer(OmxCodecBuffer & buffer)558 int32_t ComponentNode::FillThisBuffer(OmxCodecBuffer &buffer)
559 {
560     CHECK_AND_RETURN_RET_LOG(comp_ != nullptr, OMX_ErrorInvalidComponent, "comp_ is null");
561     int32_t err = OMX_ErrorBadParameter;
562     OMX_BUFFERHEADERTYPE *bufferHdrType = nullptr;
563     sptr<ICodecBuffer> codecBuffer = sptr<ICodecBuffer>();
564     if (!GetBufferById(buffer.bufferId, codecBuffer, bufferHdrType)) {
565         CODEC_LOGE("GetBufferById return false");
566         return err;
567     }
568 
569     err = codecBuffer->FillOmxBuffer(buffer, *bufferHdrType);
570     if (err != HDF_SUCCESS) {
571         CODEC_LOGE("FillOmxBuffer err [%{public}d]", err);
572         return err;
573     }
574 
575     err = OMX_FillThisBuffer(static_cast<OMX_HANDLETYPE>(comp_), bufferHdrType);
576     return err;
577 }
578 
UseBufferByType(uint32_t portIndex,OmxCodecBuffer & buffer,sptr<ICodecBuffer> codecBuffer,OMX_BUFFERHEADERTYPE * & bufferHdrType)579 int32_t ComponentNode::UseBufferByType(uint32_t portIndex, OmxCodecBuffer &buffer,
580     sptr<ICodecBuffer> codecBuffer, OMX_BUFFERHEADERTYPE *&bufferHdrType)
581 {
582     int32_t err = OMX_ErrorUndefined;
583     switch (buffer.bufferType) {
584         case CODEC_BUFFER_TYPE_AVSHARE_MEM_FD: {
585             if (compName_.find(AUDIO_CODEC_NAME) != std::string::npos) {
586                 void *addr = ::mmap(nullptr, static_cast<size_t>(buffer.allocLen),
587                     static_cast<int>(PROT_READ | PROT_WRITE), MAP_SHARED, buffer.fd, 0);
588                 CHECK_AND_RETURN_RET_LOG(addr != nullptr, OMX_ErrorBadParameter, "addr is null");
589                 err = OMX_UseBuffer(static_cast<OMX_HANDLETYPE>(comp_), &bufferHdrType, portIndex, 0, buffer.allocLen,
590                     reinterpret_cast<uint8_t *>(addr));
591                 break;
592             }
593             err = OMX_AllocateBuffer(static_cast<OMX_HANDLETYPE>(comp_), &bufferHdrType, portIndex, 0,
594                 buffer.allocLen);
595             break;
596         }
597         case CODEC_BUFFER_TYPE_HANDLE:
598         case CODEC_BUFFER_TYPE_DYNAMIC_HANDLE:
599             err = OMX_UseBuffer(static_cast<OMX_HANDLETYPE>(comp_), &bufferHdrType, portIndex, 0, buffer.allocLen,
600                 codecBuffer->GetBuffer());
601             break;
602         case CODEC_BUFFER_TYPE_DMA_MEM_FD: {
603             err = OMX_UseBuffer(static_cast<OMX_HANDLETYPE>(comp_), &bufferHdrType, portIndex, 0, 0,
604                 reinterpret_cast<uint8_t *>(&buffer.fd));
605             break;
606         }
607         default:
608             break;
609     }
610     return err;
611 }
612 
GenerateBufferId()613 uint32_t ComponentNode::GenerateBufferId()
614 {
615     std::unique_lock<std::shared_mutex> lk(mapMutex_);
616     uint32_t bufferId = 0;
617     do {
618         if (++bufferIdCount_ == 0) {
619             ++bufferIdCount_;
620         }
621         bufferId = bufferIdCount_;
622     } while (codecBufferMap_.find(bufferId) != codecBufferMap_.end());
623     return bufferId;
624 }
625 
GetBufferInfoByHeader(OMX_BUFFERHEADERTYPE * buffer)626 sptr<ICodecBuffer> ComponentNode::GetBufferInfoByHeader(OMX_BUFFERHEADERTYPE *buffer)
627 {
628     if (buffer == nullptr) {
629         CODEC_LOGE("Buffer is null");
630         return sptr<ICodecBuffer>();
631     }
632     std::shared_lock<std::shared_mutex> lk(mapMutex_);
633     auto iterHead = bufferHeaderMap_.find(buffer);
634     if (iterHead == bufferHeaderMap_.end()) {
635         CODEC_LOGE("Can not find bufferID");
636         return sptr<ICodecBuffer>();
637     }
638 
639     uint32_t bufferId = iterHead->second;
640     auto iter = codecBufferMap_.find(bufferId);
641     if (iter == codecBufferMap_.end()) {
642         CODEC_LOGE("Can not find bufferInfo by bufferId = %{public}d", bufferId);
643         return sptr<ICodecBuffer>();
644     }
645     return iter->second;
646 }
647 
GetBufferById(uint32_t bufferId,sptr<ICodecBuffer> & codecBuffer,OMX_BUFFERHEADERTYPE * & bufferHdrType)648 bool ComponentNode::GetBufferById(uint32_t bufferId, sptr<ICodecBuffer> &codecBuffer,
649                                   OMX_BUFFERHEADERTYPE *&bufferHdrType)
650 {
651     std::shared_lock<std::shared_mutex> lk(mapMutex_);
652     auto iter = codecBufferMap_.find(bufferId);
653     if ((iter == codecBufferMap_.end()) || (iter->second == nullptr)) {
654         CODEC_LOGE("Can not find bufferIndo by bufferID [%{public}d]", bufferId);
655         return false;
656     }
657 
658     auto iterHead = bufferHeaderMap_.begin();
659     for (; iterHead != bufferHeaderMap_.end(); iterHead++) {
660         if (iterHead->second == bufferId) {
661             break;
662         }
663     }
664     if ((iterHead == bufferHeaderMap_.end()) || (iterHead->first == nullptr)) {
665         CODEC_LOGE("Can not find bufferHeaderType by bufferID [%{public}d] or iterHead->first is null", bufferId);
666         return false;
667     }
668     bufferHdrType = iterHead->first;
669     codecBuffer = iter->second;
670     return true;
671 }
672 
WaitStateChange(CodecStateType objState,CodecStateType & status)673 void ComponentNode::WaitStateChange(CodecStateType objState, CodecStateType &status)
674 {
675     int32_t ret;
676     uint32_t count = 0;
677     while (status != objState && count < maxStateWaitCount) {
678         usleep(maxStateWaitTime);
679         ret = GetState(status);
680         if (ret != HDF_SUCCESS) {
681             HDF_LOGE("%{public}s: GetState error [%{public}x]", __func__, ret);
682             return;
683         }
684         count++;
685     }
686 }
687 
GetBuffCount(uint32_t & inputBuffCount,uint32_t & outputBuffCount)688 void ComponentNode::GetBuffCount(uint32_t &inputBuffCount, uint32_t &outputBuffCount)
689 {
690     std::unique_lock<std::shared_mutex> lk(mapMutex_);
691     auto iter = portIndexMap_.begin();
692     while (iter != portIndexMap_.end()) {
693         if (iter->second == 0) {
694             inputBuffCount++;
695         } else {
696             outputBuffCount++;
697         }
698         iter++;
699     }
700 }
701 
ReleaseOMXResource()702 void ComponentNode::ReleaseOMXResource()
703 {
704     std::shared_lock<std::shared_mutex> lk(mapMutex_);
705     if (codecBufferMap_.size() == 0) {
706         return;
707     }
708     CodecStateType status = CODEC_STATE_INVALID;
709     int32_t ret = GetState(status);
710     if (ret != HDF_SUCCESS) {
711         HDF_LOGE("ReleaseOMXResource GetState error [%{public}x]", ret);
712         return;
713     }
714     if (status == CODEC_STATE_EXECUTING) {
715         SendCommand(CODEC_COMMAND_STATE_SET, CODEC_STATE_IDLE, NULL);
716         WaitStateChange(CODEC_STATE_IDLE, status);
717     }
718     if (status == CODEC_STATE_IDLE) {
719         SendCommand(CODEC_COMMAND_STATE_SET, CODEC_STATE_LOADED, NULL);
720         ret = ReleaseAllBuffer();
721         if (ret != HDF_SUCCESS) {
722             HDF_LOGE("ReleaseAllBuffer err [%{public}x]", ret);
723             return;
724         }
725         WaitStateChange(CODEC_STATE_LOADED, status);
726     }
727     HDF_LOGI("%{public}s: Release OMX Resource success!", __func__);
728 }
729 
ReleaseAllBuffer()730 int32_t ComponentNode::ReleaseAllBuffer()
731 {
732     auto iter = bufferHeaderMap_.begin();
733     for (; iter != bufferHeaderMap_.end(); iter++) {
734         OMX_BUFFERHEADERTYPE *bufferHdrType = iter->first;
735         uint32_t protIndex = bufferHeaderPortMap_.find(bufferHdrType)->second;
736         auto ret = OMX_FreeBuffer((OMX_HANDLETYPE)comp_, protIndex, bufferHdrType);
737         if (ret != OMX_ErrorNone) {
738             HDF_LOGE("OMX_FreeBuffer err [%{public}x]", ret);
739             return ret;
740         }
741     }
742     HDF_LOGI("Release OMXBuffer and CodecBuffer success!");
743     return HDF_SUCCESS;
744 }
745 }  // namespace Omx
746 }  // namespace Codec
747 }  // namespace OHOS
748