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 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