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 "codec_component_service.h"
17#include <hdf_base.h>
18#include <hdf_remote_service.h>
19#include <securec.h>
20#include <malloc.h>
21#include <unistd.h>
22#include <hitrace_meter.h>
23#include "v1_0/display_composer_type.h"
24#include "v1_1/imetadata.h"
25#include "codec_log_wrapper.h"
26
27#define AUDIO_CODEC_NAME "OMX.audio"
28
29namespace OHOS {
30namespace HDI {
31namespace Codec {
32namespace V3_0 {
33
34std::mutex g_mapperMtx;
35sptr<OHOS::HDI::Display::Buffer::V1_0::IMapper> g_mapperService;
36
37sptr<OHOS::HDI::Display::Buffer::V1_0::IMapper> GetMapperService()
38{
39    std::lock_guard<std::mutex> lk(g_mapperMtx);
40    if (g_mapperService) {
41        return g_mapperService;
42    }
43    g_mapperService = OHOS::HDI::Display::Buffer::V1_0::IMapper::Get(true);
44    if (g_mapperService) {
45        CODEC_LOGI("get IMapper succ");
46        return g_mapperService;
47    }
48    CODEC_LOGE("get IMapper failed");
49    return nullptr;
50}
51
52std::mutex g_metaMtx;
53sptr<OHOS::HDI::Display::Buffer::V1_1::IMetadata> g_metaService;
54
55sptr<OHOS::HDI::Display::Buffer::V1_1::IMetadata> GetMetaService()
56{
57    std::lock_guard<std::mutex> lk(g_metaMtx);
58    if (g_metaService) {
59        return g_metaService;
60    }
61    g_metaService = OHOS::HDI::Display::Buffer::V1_1::IMetadata::Get(true);
62    if (g_metaService) {
63        CODEC_LOGI("get IMetadata succ");
64        return g_metaService;
65    }
66    CODEC_LOGE("get IMetadata failed");
67    return nullptr;
68}
69
70void BufferDestructor(BufferHandle* handle)
71{
72    if (handle == nullptr) {
73        return;
74    }
75    sptr<OHOS::HDI::Display::Buffer::V1_0::IMapper> mapper = GetMapperService();
76    if (mapper == nullptr) {
77        return;
78    }
79    sptr<NativeBuffer> buffer = new NativeBuffer();
80    buffer->SetBufferHandle(handle, true);
81    mapper->FreeMem(buffer);
82}
83
84bool ReWrapNativeBuffer(sptr<NativeBuffer>& buffer)
85{
86    if (buffer == nullptr) {
87        return true;
88    }
89    BufferHandle* handle = buffer->Move();
90    if (handle == nullptr) {
91        return true;
92    }
93    buffer->SetBufferHandle(handle, true, BufferDestructor);
94    sptr<OHOS::HDI::Display::Buffer::V1_1::IMetadata> meta = GetMetaService();
95    if (meta == nullptr) {
96        return false;
97    }
98    int32_t ret = meta->RegisterBuffer(buffer);
99    if (ret != Display::Composer::V1_0::DISPLAY_SUCCESS &&
100        ret != Display::Composer::V1_0::DISPLAY_NOT_SUPPORT) {
101        CODEC_LOGE("RegisterBuffer failed, ret = %{public}d", ret);
102        return false;
103    }
104    return true;
105}
106
107bool CodecComponentService::ReWrapNativeBufferInOmxBuffer(const OmxCodecBuffer &inBuffer)
108{
109    if (!isIPCMode_) {
110        return true;
111    }
112    return ReWrapNativeBuffer(const_cast<OmxCodecBuffer &>(inBuffer).bufferhandle);
113}
114
115CodecComponentService::CodecComponentService(const std::shared_ptr<OHOS::Codec::Omx::ComponentNode> &node,
116    const std::shared_ptr<OHOS::Codec::Omx::ComponentMgr> mgr, const std::string name)
117{
118    name_ = name;
119    node_ = node;
120    mgr_  = mgr;
121    isIPCMode_ = (HdfRemoteGetCallingPid() == getpid() ? false : true);
122#ifdef SUPPORT_ROLE
123    SetComponentRole();
124#endif
125}
126CodecComponentService::~CodecComponentService()
127{
128    if (node_ != nullptr) {
129        node_->ReleaseOMXResource();
130        int32_t ret = node_->CloseHandle();
131        if (ret != HDF_SUCCESS) {
132            CODEC_LOGE("CloseHandle failed, err[%{public}d]", ret);
133        }
134        node_ = nullptr;
135        ReleaseCache();
136    }
137    name_ = "";
138    mgr_ = nullptr;
139}
140
141void CodecComponentService::ReleaseCache()
142{
143#ifdef CONFIG_USE_JEMALLOC_DFX_INTF
144    mallopt(M_FLUSH_THREAD_CACHE, 0);
145#endif
146}
147
148int32_t CodecComponentService::GetComponentVersion(CompVerInfo &verInfo)
149{
150    HITRACE_METER_NAME(HITRACE_TAG_HDF, "HDFCodecGetComponentVersion");
151    return node_->GetComponentVersion(verInfo);
152}
153
154int32_t CodecComponentService::SendCommand(CodecCommandType cmd, uint32_t param, const std::vector<int8_t> &cmdData)
155{
156    HITRACE_METER_NAME(HITRACE_TAG_HDF, "HDFCodecSendCommand");
157    CODEC_LOGI("commandType: [%{public}d], command [%{public}d]", cmd, param);
158    return node_->SendCommand(cmd, param, const_cast<int8_t *>(cmdData.data()));
159}
160
161int32_t CodecComponentService::GetParameter(uint32_t index, const std::vector<int8_t> &inParamStruct,
162                                            std::vector<int8_t> &outParamStruct)
163{
164    HITRACE_METER_NAME(HITRACE_TAG_HDF, "HDFCodecGetParameter");
165    CODEC_LOGD("index [%{public}x]", index);
166    outParamStruct = inParamStruct;
167    return node_->GetParameter(static_cast<enum OMX_INDEXTYPE>(index), outParamStruct.data());
168}
169
170int32_t CodecComponentService::SetParameter(uint32_t index, const std::vector<int8_t> &paramStruct)
171{
172    HITRACE_METER_NAME(HITRACE_TAG_HDF, "HDFCodecSetParameter");
173    CODEC_LOGD("index [%{public}x]", index);
174    return node_->SetParameter(static_cast<enum OMX_INDEXTYPE>(index), paramStruct.data());
175}
176
177int32_t CodecComponentService::GetConfig(uint32_t index, const std::vector<int8_t> &inCfgStruct,
178                                         std::vector<int8_t> &outCfgStruct)
179{
180    HITRACE_METER_NAME(HITRACE_TAG_HDF, "HDFCodecGetConfig");
181    CODEC_LOGD("index [%{public}x]", index);
182    outCfgStruct = inCfgStruct;
183    return node_->GetConfig(static_cast<enum OMX_INDEXTYPE>(index), outCfgStruct.data());
184}
185
186int32_t CodecComponentService::SetConfig(uint32_t index, const std::vector<int8_t> &cfgStruct)
187{
188    HITRACE_METER_NAME(HITRACE_TAG_HDF, "HDFCodecSetConfig");
189    CODEC_LOGD("index [%{public}x]", index);
190    return node_->SetConfig(static_cast<enum OMX_INDEXTYPE>(index), cfgStruct.data());
191}
192
193int32_t CodecComponentService::GetExtensionIndex(const std::string &paramName, uint32_t &indexType)
194{
195    HITRACE_METER_NAME(HITRACE_TAG_HDF, "HDFCodecGetExtensionIndex");
196    CODEC_LOGI("paramName [%{public}s]", paramName.c_str());
197    return node_->GetExtensionIndex(paramName.c_str(), indexType);
198}
199
200int32_t CodecComponentService::GetState(CodecStateType &state)
201{
202    HITRACE_METER_NAME(HITRACE_TAG_HDF, "HDFCodecGetState");
203    return node_->GetState(state);
204}
205
206int32_t CodecComponentService::ComponentTunnelRequest(uint32_t port, int32_t tunneledComp, uint32_t tunneledPort,
207                                                      const CodecTunnelSetupType &inTunnelSetup,
208                                                      CodecTunnelSetupType &outTunnelSetup)
209{
210    HITRACE_METER_NAME(HITRACE_TAG_HDF, "HDFCodecComponentTunnelRequest");
211    CODEC_LOGI("port [%{public}d]", port);
212    outTunnelSetup = inTunnelSetup;
213    return node_->ComponentTunnelRequest(port, tunneledComp, tunneledPort, outTunnelSetup);
214}
215
216int32_t CodecComponentService::UseBuffer(uint32_t portIndex, const OmxCodecBuffer &inBuffer, OmxCodecBuffer &outBuffer)
217{
218    HITRACE_METER_NAME(HITRACE_TAG_HDF, "HDFCodecUseBuffer");
219    CODEC_LOGD("portIndex: [%{public}d]", portIndex);
220    if (!ReWrapNativeBufferInOmxBuffer(inBuffer)) {
221        return HDF_FAILURE;
222    }
223    outBuffer = const_cast<OmxCodecBuffer &>(inBuffer);
224
225    if (outBuffer.fd >= 0 && isIPCMode_ && outBuffer.bufferType != CODEC_BUFFER_TYPE_AVSHARE_MEM_FD &&
226        outBuffer.bufferType != CODEC_BUFFER_TYPE_DMA_MEM_FD &&
227        name_.find(AUDIO_CODEC_NAME) == std::string::npos) {
228        close(outBuffer.fd);
229        outBuffer.fd = -1;
230    }
231    if (outBuffer.fenceFd >= 0) {
232        close(outBuffer.fenceFd);
233        outBuffer.fenceFd = -1;
234    }
235
236    return node_->UseBuffer(portIndex, outBuffer);
237}
238
239int32_t CodecComponentService::AllocateBuffer(uint32_t portIndex, const OmxCodecBuffer &inBuffer,
240                                              OmxCodecBuffer &outBuffer)
241{
242    HITRACE_METER_NAME(HITRACE_TAG_HDF, "HDFCodecAllocateBuffer");
243    CODEC_LOGD("portIndex: [%{public}d]", portIndex);
244    outBuffer = inBuffer;
245    return node_->AllocateBuffer(portIndex, outBuffer);
246}
247
248int32_t CodecComponentService::FreeBuffer(uint32_t portIndex, const OmxCodecBuffer &buffer)
249{
250    HITRACE_METER_NAME(HITRACE_TAG_HDF, "HDFCodecFreeBuffer");
251    OmxCodecBuffer &bufferTemp = const_cast<OmxCodecBuffer &>(buffer);
252    CODEC_LOGD("portIndex: [%{public}d], bufferId: [%{public}d]", portIndex, buffer.bufferId);
253    int32_t ret = node_->FreeBuffer(portIndex, buffer);
254    ReleaseCache();
255    if (isIPCMode_ && bufferTemp.fd >= 0) {
256        close(bufferTemp.fd);
257        bufferTemp.fd = -1;
258    }
259
260    return ret;
261}
262
263int32_t CodecComponentService::EmptyThisBuffer(const OmxCodecBuffer &buffer)
264{
265    HITRACE_METER_NAME(HITRACE_TAG_HDF, "HDFCodecEmptyThisBuffer");
266    if (!ReWrapNativeBufferInOmxBuffer(buffer)) {
267        return HDF_FAILURE;
268    }
269    OmxCodecBuffer &bufferTemp = const_cast<OmxCodecBuffer &>(buffer);
270    int32_t ret = node_->EmptyThisBuffer(bufferTemp);
271    if (isIPCMode_ && bufferTemp.fd >= 0) {
272        close(bufferTemp.fd);
273        bufferTemp.fd = -1;
274    }
275
276    return ret;
277}
278
279int32_t CodecComponentService::FillThisBuffer(const OmxCodecBuffer &buffer)
280{
281    HITRACE_METER_NAME(HITRACE_TAG_HDF, "HDFCodecFillThisBuffer");
282    if (!ReWrapNativeBufferInOmxBuffer(buffer)) {
283        return HDF_FAILURE;
284    }
285    OmxCodecBuffer &bufferTemp = const_cast<OmxCodecBuffer &>(buffer);
286    int32_t ret = node_->FillThisBuffer(bufferTemp);
287    if (isIPCMode_ && bufferTemp.fd >= 0) {
288        close(bufferTemp.fd);
289        bufferTemp.fd = -1;
290    }
291
292    return ret;
293}
294
295int32_t CodecComponentService::SetCallbacks(const sptr<ICodecCallback> &callbacks, int64_t appData)
296{
297    HITRACE_METER_NAME(HITRACE_TAG_HDF, "HDFCodecSetCallbacks");
298    CODEC_LOGI("service impl!");
299    CHECK_AND_RETURN_RET_LOG(callbacks != nullptr, HDF_ERR_INVALID_PARAM, "callbacks is null");
300    return node_->SetCallbacks(callbacks, appData);
301}
302
303int32_t CodecComponentService::ComponentDeInit()
304{
305    HITRACE_METER_NAME(HITRACE_TAG_HDF, "HDFCodecComponentDeInit");
306    CODEC_LOGI("service impl!");
307    return node_->ComponentDeInit();
308}
309
310int32_t CodecComponentService::UseEglImage(uint32_t portIndex, const OmxCodecBuffer &inBuffer,
311                                           OmxCodecBuffer &outBuffer, const std::vector<int8_t> &eglImage)
312{
313    HITRACE_METER_NAME(HITRACE_TAG_HDF, "HDFCodecUseEglImage");
314    CODEC_LOGI("portIndex [%{public}d]", portIndex);
315    outBuffer = inBuffer;
316    return node_->UseEglImage(outBuffer, portIndex, eglImage.data());
317}
318
319int32_t CodecComponentService::ComponentRoleEnum(std::vector<uint8_t> &role, uint32_t index)
320{
321    HITRACE_METER_NAME(HITRACE_TAG_HDF, "HDFCodecComponentRoleEnum");
322    CODEC_LOGI("index [%{public}d]", index);
323    return node_->ComponentRoleEnum(role, index);
324}
325
326void CodecComponentService::SetComponentRole()
327{
328    HITRACE_METER_NAME(HITRACE_TAG_HDF, "HDFCodecSetComponentRole");
329    if (name_ == "") {
330        CODEC_LOGE("compName is null");
331        return;
332    }
333    OHOS::Codec::Omx::CodecOMXCore *core;
334    auto err = mgr_->GetCoreOfComponent(core, name_);
335    if (err != HDF_SUCCESS) {
336        CODEC_LOGE("core is null");
337        return;
338    }
339
340    std::vector<std::string> roles;
341    int32_t ret = core->GetRolesOfComponent(name_, roles);
342    if (ret != HDF_SUCCESS) {
343        CODEC_LOGE("GetRoleOfComponent return err [%{public}d]", ret);
344        return;
345    }
346    if (roles.empty()) {
347        CODEC_LOGE("role of component is empty");
348        return;
349    }
350    uint32_t roleIndex = 0;
351    CODEC_LOGI("RoleName = [%{public}s]", roles[roleIndex].c_str());
352
353    OMX_PARAM_COMPONENTROLETYPE role;
354    errno_t res = strncpy_s(reinterpret_cast<char *>(role.cRole), OMX_MAX_STRINGNAME_SIZE,
355                            roles[roleIndex].c_str(), roles[roleIndex].length());
356    if (res != EOK) {
357        CODEC_LOGE("strncpy_s return err [%{public}d]", err);
358        return;
359    }
360    role.nSize = sizeof(role);
361    ret = node_->SetParameter(OMX_IndexParamStandardComponentRole, reinterpret_cast<int8_t *>(&role));
362    if (ret != HDF_SUCCESS) {
363        CODEC_LOGE("OMX_IndexParamStandardComponentRole err [%{public}d]", ret);
364    }
365}
366
367int32_t CodecComponentService::SetParameterWithBuffer(uint32_t index, const std::vector<int8_t>& paramStruct,
368                                                      const OmxCodecBuffer& inBuffer)
369{
370    return node_->SetParameterWithBuffer(index, paramStruct, inBuffer);
371}
372
373const std::string &CodecComponentService::GetComponentCompName() const
374{
375    return name_;
376}
377
378void CodecComponentService::GetComponentNode(std::shared_ptr<OHOS::Codec::Omx::ComponentNode> &dumpNode_)
379{
380    dumpNode_ = node_;
381}
382
383}  // namespace V3_0
384}  // namespace Codec
385}  // namespace HDI
386}  // namespace OHOS
387