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