1094332d3Sopenharmony_ci/*
2094332d3Sopenharmony_ci * Copyright (c) 2022-2023 Shenzhen Kaihong DID Co., Ltd.
3094332d3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4094332d3Sopenharmony_ci * you may not use this file except in compliance with the License.
5094332d3Sopenharmony_ci * You may obtain a copy of the License at
6094332d3Sopenharmony_ci *
7094332d3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8094332d3Sopenharmony_ci *
9094332d3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10094332d3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11094332d3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12094332d3Sopenharmony_ci * See the License for the specific language governing permissions and
13094332d3Sopenharmony_ci * limitations under the License.
14094332d3Sopenharmony_ci */
15094332d3Sopenharmony_ci
16094332d3Sopenharmony_ci#include <osal_mem.h>
17094332d3Sopenharmony_ci#include <servmgr_hdi.h>
18094332d3Sopenharmony_ci#include "codec_component_manager.h"
19094332d3Sopenharmony_ci#include "codec_internal.h"
20094332d3Sopenharmony_ci#include "codec_log_wrapper.h"
21094332d3Sopenharmony_ci#include "codec_util.h"
22094332d3Sopenharmony_ci#include "codec_types.h"
23094332d3Sopenharmony_ci
24094332d3Sopenharmony_cistruct CodecComponentManagerProxy {
25094332d3Sopenharmony_ci    struct CodecComponentManager instance;
26094332d3Sopenharmony_ci    struct HdfRemoteService *remoteOmx;
27094332d3Sopenharmony_ci};
28094332d3Sopenharmony_ci
29094332d3Sopenharmony_cistatic struct CodecComponentManagerProxy g_codecComponentManagerProxy = {
30094332d3Sopenharmony_ci    .instance = {
31094332d3Sopenharmony_ci        .GetComponentNum = NULL,
32094332d3Sopenharmony_ci        .GetComponentCapabilityList = NULL,
33094332d3Sopenharmony_ci        .CreateComponent = NULL,
34094332d3Sopenharmony_ci        .DestroyComponent = NULL,
35094332d3Sopenharmony_ci        .AsObject = NULL,
36094332d3Sopenharmony_ci    },
37094332d3Sopenharmony_ci    .remoteOmx = NULL,
38094332d3Sopenharmony_ci};
39094332d3Sopenharmony_ci
40094332d3Sopenharmony_cistatic void ReleaseSbuf(struct HdfSBuf *data, struct HdfSBuf *reply)
41094332d3Sopenharmony_ci{
42094332d3Sopenharmony_ci    if (data != NULL) {
43094332d3Sopenharmony_ci        HdfSbufRecycle(data);
44094332d3Sopenharmony_ci    }
45094332d3Sopenharmony_ci    if (reply != NULL) {
46094332d3Sopenharmony_ci        HdfSbufRecycle(reply);
47094332d3Sopenharmony_ci    }
48094332d3Sopenharmony_ci}
49094332d3Sopenharmony_ci
50094332d3Sopenharmony_cistatic int32_t GetComponentNum()
51094332d3Sopenharmony_ci{
52094332d3Sopenharmony_ci    int32_t num = 0;
53094332d3Sopenharmony_ci    struct HdfSBuf *data = HdfSbufTypedObtain(SBUF_IPC);
54094332d3Sopenharmony_ci    if (data == NULL) {
55094332d3Sopenharmony_ci        CODEC_LOGE("Failed to obtain");
56094332d3Sopenharmony_ci        return HDF_FAILURE;
57094332d3Sopenharmony_ci    }
58094332d3Sopenharmony_ci    struct HdfSBuf *reply = HdfSbufTypedObtain(SBUF_IPC);
59094332d3Sopenharmony_ci    if (reply == NULL) {
60094332d3Sopenharmony_ci        CODEC_LOGE("Failed to obtain reply");
61094332d3Sopenharmony_ci        HdfSbufRecycle(data);
62094332d3Sopenharmony_ci        return HDF_FAILURE;
63094332d3Sopenharmony_ci    }
64094332d3Sopenharmony_ci
65094332d3Sopenharmony_ci    if (!HdfRemoteServiceWriteInterfaceToken(g_codecComponentManagerProxy.remoteOmx, data)) {
66094332d3Sopenharmony_ci        CODEC_LOGE("write interface token failed");
67094332d3Sopenharmony_ci        ReleaseSbuf(data, reply);
68094332d3Sopenharmony_ci        return HDF_FAILURE;
69094332d3Sopenharmony_ci    }
70094332d3Sopenharmony_ci
71094332d3Sopenharmony_ci    if (g_codecComponentManagerProxy.remoteOmx->dispatcher->Dispatch(
72094332d3Sopenharmony_ci        g_codecComponentManagerProxy.remoteOmx, CMD_CODEC_GET_COMPONENT_NUM, data, reply) != HDF_SUCCESS) {
73094332d3Sopenharmony_ci        CODEC_LOGE("dispatch request failed!");
74094332d3Sopenharmony_ci        ReleaseSbuf(data, reply);
75094332d3Sopenharmony_ci        return HDF_FAILURE;
76094332d3Sopenharmony_ci    }
77094332d3Sopenharmony_ci
78094332d3Sopenharmony_ci    if (!HdfSbufReadInt32(reply, &num)) {
79094332d3Sopenharmony_ci        CODEC_LOGE("read dataBlock->role failed!");
80094332d3Sopenharmony_ci        ReleaseSbuf(data, reply);
81094332d3Sopenharmony_ci        return HDF_FAILURE;
82094332d3Sopenharmony_ci    }
83094332d3Sopenharmony_ci
84094332d3Sopenharmony_ci    ReleaseSbuf(data, reply);
85094332d3Sopenharmony_ci    return num;
86094332d3Sopenharmony_ci}
87094332d3Sopenharmony_ci
88094332d3Sopenharmony_cistatic int32_t GetComponentCapabilityList(CodecCompCapability *capList, int32_t count)
89094332d3Sopenharmony_ci{
90094332d3Sopenharmony_ci    struct HdfSBuf *data = HdfSbufTypedObtain(SBUF_IPC);
91094332d3Sopenharmony_ci    int32_t num = GetComponentNum();
92094332d3Sopenharmony_ci    if (data == NULL || count <= 0 || count > num) {
93094332d3Sopenharmony_ci        CODEC_LOGE("Failed to obtain");
94094332d3Sopenharmony_ci        return HDF_FAILURE;
95094332d3Sopenharmony_ci    }
96094332d3Sopenharmony_ci    struct HdfSBuf *reply = HdfSbufTypedObtain(SBUF_IPC);
97094332d3Sopenharmony_ci    if (reply == NULL) {
98094332d3Sopenharmony_ci        CODEC_LOGE("Failed to obtain reply");
99094332d3Sopenharmony_ci        HdfSbufRecycle(data);
100094332d3Sopenharmony_ci        return HDF_FAILURE;
101094332d3Sopenharmony_ci    }
102094332d3Sopenharmony_ci
103094332d3Sopenharmony_ci    if (!HdfRemoteServiceWriteInterfaceToken(g_codecComponentManagerProxy.remoteOmx, data)) {
104094332d3Sopenharmony_ci        CODEC_LOGE("write interface token failed");
105094332d3Sopenharmony_ci        ReleaseSbuf(data, reply);
106094332d3Sopenharmony_ci        return HDF_FAILURE;
107094332d3Sopenharmony_ci    }
108094332d3Sopenharmony_ci
109094332d3Sopenharmony_ci    if (!HdfSbufWriteInt32(data, count)) {
110094332d3Sopenharmony_ci        CODEC_LOGE("write count failed!");
111094332d3Sopenharmony_ci        ReleaseSbuf(data, reply);
112094332d3Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
113094332d3Sopenharmony_ci    }
114094332d3Sopenharmony_ci
115094332d3Sopenharmony_ci    if (g_codecComponentManagerProxy.remoteOmx->dispatcher->Dispatch(g_codecComponentManagerProxy.remoteOmx,
116094332d3Sopenharmony_ci                                                                     CMD_CODEC_GET_COMPONENT_CAPABILITY_LIST, data,
117094332d3Sopenharmony_ci                                                                     reply) != HDF_SUCCESS) {
118094332d3Sopenharmony_ci        CODEC_LOGE("dispatch request failed!");
119094332d3Sopenharmony_ci        ReleaseSbuf(data, reply);
120094332d3Sopenharmony_ci        return HDF_FAILURE;
121094332d3Sopenharmony_ci    }
122094332d3Sopenharmony_ci
123094332d3Sopenharmony_ci    for (int32_t i = 0; i < count; i++) {
124094332d3Sopenharmony_ci        if (!CodecCompCapabilityBlockUnmarshalling(reply, &(capList)[i])) {
125094332d3Sopenharmony_ci            CODEC_LOGE("read capbility %{public}d from sbuf failed!", i);
126094332d3Sopenharmony_ci            ReleaseSbuf(data, reply);
127094332d3Sopenharmony_ci            return HDF_FAILURE;
128094332d3Sopenharmony_ci        }
129094332d3Sopenharmony_ci    }
130094332d3Sopenharmony_ci
131094332d3Sopenharmony_ci    ReleaseSbuf(data, reply);
132094332d3Sopenharmony_ci    return HDF_SUCCESS;
133094332d3Sopenharmony_ci}
134094332d3Sopenharmony_ci
135094332d3Sopenharmony_cistatic int32_t FillHdfSBufData(struct HdfSBuf *data, char *compName, int64_t appData,
136094332d3Sopenharmony_ci                               struct CodecCallbackType *callback)
137094332d3Sopenharmony_ci{
138094332d3Sopenharmony_ci    if (!HdfRemoteServiceWriteInterfaceToken(g_codecComponentManagerProxy.remoteOmx, data)) {
139094332d3Sopenharmony_ci        CODEC_LOGE("write interface token failed");
140094332d3Sopenharmony_ci        return HDF_FAILURE;
141094332d3Sopenharmony_ci    }
142094332d3Sopenharmony_ci    if (!HdfSbufWriteString(data, compName)) {
143094332d3Sopenharmony_ci        CODEC_LOGE("write paramName failed!");
144094332d3Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
145094332d3Sopenharmony_ci    }
146094332d3Sopenharmony_ci    if (!HdfSbufWriteInt64(data, appData)) {
147094332d3Sopenharmony_ci        CODEC_LOGE("write appData failed!");
148094332d3Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
149094332d3Sopenharmony_ci    }
150094332d3Sopenharmony_ci    if (HdfSbufWriteRemoteService(data, callback->remote) != 0) {
151094332d3Sopenharmony_ci        CODEC_LOGE("write callback failed!");
152094332d3Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
153094332d3Sopenharmony_ci    }
154094332d3Sopenharmony_ci    return HDF_SUCCESS;
155094332d3Sopenharmony_ci}
156094332d3Sopenharmony_ci
157094332d3Sopenharmony_cistatic int32_t CreateComponent(struct CodecComponentType **component, uint32_t *componentId, char *compName,
158094332d3Sopenharmony_ci                               int64_t appData, struct CodecCallbackType *callback)
159094332d3Sopenharmony_ci{
160094332d3Sopenharmony_ci    struct HdfSBuf *data = HdfSbufTypedObtain(SBUF_IPC);
161094332d3Sopenharmony_ci    struct HdfSBuf *reply = HdfSbufTypedObtain(SBUF_IPC);
162094332d3Sopenharmony_ci    if (data == NULL || reply == NULL || componentId == NULL) {
163094332d3Sopenharmony_ci        CODEC_LOGE("HdfSubf malloc failed!");
164094332d3Sopenharmony_ci        ReleaseSbuf(data, reply);
165094332d3Sopenharmony_ci        return HDF_ERR_MALLOC_FAIL;
166094332d3Sopenharmony_ci    }
167094332d3Sopenharmony_ci
168094332d3Sopenharmony_ci    int32_t ret = FillHdfSBufData(data, compName, appData, callback);
169094332d3Sopenharmony_ci    if (ret != HDF_SUCCESS) {
170094332d3Sopenharmony_ci        ReleaseSbuf(data, reply);
171094332d3Sopenharmony_ci        return ret;
172094332d3Sopenharmony_ci    }
173094332d3Sopenharmony_ci
174094332d3Sopenharmony_ci    ret = g_codecComponentManagerProxy.remoteOmx->dispatcher->Dispatch(g_codecComponentManagerProxy.remoteOmx,
175094332d3Sopenharmony_ci                                                                       CMD_CREATE_COMPONENT, data, reply);
176094332d3Sopenharmony_ci    if (ret != HDF_SUCCESS) {
177094332d3Sopenharmony_ci        CODEC_LOGE("call failed! error code is %{public}d", ret);
178094332d3Sopenharmony_ci        ReleaseSbuf(data, reply);
179094332d3Sopenharmony_ci        return ret;
180094332d3Sopenharmony_ci    }
181094332d3Sopenharmony_ci
182094332d3Sopenharmony_ci    struct HdfRemoteService *componentRemote = HdfSbufReadRemoteService(reply);
183094332d3Sopenharmony_ci    if (componentRemote == NULL) {
184094332d3Sopenharmony_ci        CODEC_LOGE("read componentRemote failed!");
185094332d3Sopenharmony_ci        ReleaseSbuf(data, reply);
186094332d3Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
187094332d3Sopenharmony_ci    }
188094332d3Sopenharmony_ci    if (!HdfSbufReadUint32(reply, componentId)) {
189094332d3Sopenharmony_ci        CODEC_LOGE("read componentId failed!");
190094332d3Sopenharmony_ci        ReleaseSbuf(data, reply);
191094332d3Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
192094332d3Sopenharmony_ci    }
193094332d3Sopenharmony_ci    *component = CodecComponentTypeGet(componentRemote);
194094332d3Sopenharmony_ci    ReleaseSbuf(data, reply);
195094332d3Sopenharmony_ci#ifdef CONFIG_USE_JEMALLOC_DFX_INTF
196094332d3Sopenharmony_ci    ReleaseCodecCache();
197094332d3Sopenharmony_ci#endif
198094332d3Sopenharmony_ci    return ret;
199094332d3Sopenharmony_ci}
200094332d3Sopenharmony_ci
201094332d3Sopenharmony_cistatic int32_t DestroyComponent(uint32_t componentId)
202094332d3Sopenharmony_ci{
203094332d3Sopenharmony_ci    int32_t ret;
204094332d3Sopenharmony_ci
205094332d3Sopenharmony_ci    struct HdfSBuf *data = HdfSbufTypedObtain(SBUF_IPC);
206094332d3Sopenharmony_ci    struct HdfSBuf *reply = HdfSbufTypedObtain(SBUF_IPC);
207094332d3Sopenharmony_ci    if (data == NULL || reply == NULL) {
208094332d3Sopenharmony_ci        CODEC_LOGE("HdfSubf malloc failed!");
209094332d3Sopenharmony_ci        ReleaseSbuf(data, reply);
210094332d3Sopenharmony_ci        return HDF_ERR_MALLOC_FAIL;
211094332d3Sopenharmony_ci    }
212094332d3Sopenharmony_ci
213094332d3Sopenharmony_ci    if (!HdfRemoteServiceWriteInterfaceToken(g_codecComponentManagerProxy.remoteOmx, data)) {
214094332d3Sopenharmony_ci        CODEC_LOGE("write interface token failed");
215094332d3Sopenharmony_ci        ReleaseSbuf(data, reply);
216094332d3Sopenharmony_ci        return HDF_FAILURE;
217094332d3Sopenharmony_ci    }
218094332d3Sopenharmony_ci
219094332d3Sopenharmony_ci    if (!HdfSbufWriteUint32(data, componentId)) {
220094332d3Sopenharmony_ci        CODEC_LOGE("write componentId failed!");
221094332d3Sopenharmony_ci        ReleaseSbuf(data, reply);
222094332d3Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
223094332d3Sopenharmony_ci    }
224094332d3Sopenharmony_ci
225094332d3Sopenharmony_ci    ret = g_codecComponentManagerProxy.remoteOmx->dispatcher->Dispatch(g_codecComponentManagerProxy.remoteOmx,
226094332d3Sopenharmony_ci                                                                       CMD_DESTROY_COMPONENT, data, reply);
227094332d3Sopenharmony_ci    if (ret != HDF_SUCCESS) {
228094332d3Sopenharmony_ci        CODEC_LOGE("call failed! error code is %{public}d", ret);
229094332d3Sopenharmony_ci        ReleaseSbuf(data, reply);
230094332d3Sopenharmony_ci        return ret;
231094332d3Sopenharmony_ci    }
232094332d3Sopenharmony_ci    ReleaseSbuf(data, reply);
233094332d3Sopenharmony_ci#ifdef CONFIG_USE_JEMALLOC_DFX_INTF
234094332d3Sopenharmony_ci    ReleaseCodecCache();
235094332d3Sopenharmony_ci#endif
236094332d3Sopenharmony_ci    return ret;
237094332d3Sopenharmony_ci}
238094332d3Sopenharmony_ci
239094332d3Sopenharmony_cistatic int32_t InitCodecComponentManagerProxy(void)
240094332d3Sopenharmony_ci{
241094332d3Sopenharmony_ci    if (g_codecComponentManagerProxy.remoteOmx != NULL) {
242094332d3Sopenharmony_ci        return HDF_SUCCESS;
243094332d3Sopenharmony_ci    }
244094332d3Sopenharmony_ci
245094332d3Sopenharmony_ci    struct HDIServiceManager *serviceMgr = HDIServiceManagerGet();
246094332d3Sopenharmony_ci    if (serviceMgr == NULL) {
247094332d3Sopenharmony_ci        CODEC_LOGE("HDIServiceManager not found!");
248094332d3Sopenharmony_ci        return HDF_FAILURE;
249094332d3Sopenharmony_ci    }
250094332d3Sopenharmony_ci
251094332d3Sopenharmony_ci    struct HdfRemoteService *remoteOmx = serviceMgr->GetService(serviceMgr, CODEC_HDI_OMX_SERVICE_NAME);
252094332d3Sopenharmony_ci    HDIServiceManagerRelease(serviceMgr);
253094332d3Sopenharmony_ci    if (remoteOmx == NULL) {
254094332d3Sopenharmony_ci        CODEC_LOGE("CodecComponentTypeService not found!");
255094332d3Sopenharmony_ci        return HDF_FAILURE;
256094332d3Sopenharmony_ci    }
257094332d3Sopenharmony_ci    if (!HdfRemoteServiceSetInterfaceDesc(remoteOmx, "ohos.hdi.codec_service")) {
258094332d3Sopenharmony_ci        CODEC_LOGE("failed to init interface desc");
259094332d3Sopenharmony_ci        HdfRemoteServiceRecycle(remoteOmx);
260094332d3Sopenharmony_ci        return HDF_FAILURE;
261094332d3Sopenharmony_ci    }
262094332d3Sopenharmony_ci
263094332d3Sopenharmony_ci    g_codecComponentManagerProxy.remoteOmx = remoteOmx;
264094332d3Sopenharmony_ci    g_codecComponentManagerProxy.instance.GetComponentNum = GetComponentNum;
265094332d3Sopenharmony_ci    g_codecComponentManagerProxy.instance.GetComponentCapabilityList = GetComponentCapabilityList;
266094332d3Sopenharmony_ci    g_codecComponentManagerProxy.instance.CreateComponent = CreateComponent;
267094332d3Sopenharmony_ci    g_codecComponentManagerProxy.instance.DestroyComponent = DestroyComponent;
268094332d3Sopenharmony_ci
269094332d3Sopenharmony_ci    return HDF_SUCCESS;
270094332d3Sopenharmony_ci}
271094332d3Sopenharmony_ci
272094332d3Sopenharmony_cistruct CodecComponentManager *GetCodecComponentManager(void)
273094332d3Sopenharmony_ci{
274094332d3Sopenharmony_ci    if (InitCodecComponentManagerProxy() != HDF_SUCCESS) {
275094332d3Sopenharmony_ci        return NULL;
276094332d3Sopenharmony_ci    }
277094332d3Sopenharmony_ci    return &g_codecComponentManagerProxy.instance;
278094332d3Sopenharmony_ci}
279094332d3Sopenharmony_ci
280094332d3Sopenharmony_civoid CodecComponentManagerRelease(void)
281094332d3Sopenharmony_ci{
282094332d3Sopenharmony_ci    if (g_codecComponentManagerProxy.remoteOmx != NULL) {
283094332d3Sopenharmony_ci        HdfRemoteServiceRecycle(g_codecComponentManagerProxy.remoteOmx);
284094332d3Sopenharmony_ci        g_codecComponentManagerProxy.remoteOmx = NULL;
285094332d3Sopenharmony_ci    }
286094332d3Sopenharmony_ci}