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 *>(¶mDst));
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