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 <hdf_log.h>
17 #include <hdf_remote_service.h>
18 #include <osal_mem.h>
19 #include "codec_callback_if.h"
20 #include "codec_internal.h"
21 #include "codec_log_wrapper.h"
22 #include "codec_types.h"
23 
24 struct CodecCallbackTypeProxy {
25     struct CodecCallbackType instance;
26     struct HdfRemoteService *remote;
27 };
28 
ReleaseSbuf(struct HdfSBuf * data,struct HdfSBuf * reply)29 static void ReleaseSbuf(struct HdfSBuf *data, struct HdfSBuf *reply)
30 {
31     if (data != NULL) {
32         HdfSbufRecycle(data);
33     }
34     if (reply != NULL) {
35         HdfSbufRecycle(reply);
36     }
37 }
38 
CodecCallbackTypeProxyCall(struct CodecCallbackType * self,int32_t id,struct HdfSBuf * data,struct HdfSBuf * reply)39 static int32_t CodecCallbackTypeProxyCall(struct CodecCallbackType *self, int32_t id, struct HdfSBuf *data,
40                                           struct HdfSBuf *reply)
41 {
42     if (self == NULL) {
43         CODEC_LOGE("invalid parameter");
44         return HDF_ERR_INVALID_PARAM;
45     }
46     if (self->remote == NULL || self->remote->dispatcher == NULL || self->remote->dispatcher->Dispatch == NULL) {
47         CODEC_LOGE("obj is null");
48         return HDF_ERR_INVALID_OBJECT;
49     }
50     return self->remote->dispatcher->Dispatch(self->remote, id, data, reply);
51 }
52 
WriteArray(struct HdfSBuf * data,int8_t * array,uint32_t arrayLen)53 static int32_t WriteArray(struct HdfSBuf *data, int8_t *array, uint32_t arrayLen)
54 {
55     if (!HdfSbufWriteUint32(data, arrayLen)) {
56         CODEC_LOGE("write appData failed!");
57         return HDF_ERR_INVALID_PARAM;
58     }
59     for (uint32_t i = 0; i < arrayLen; i++) {
60         if (!HdfSbufWriteInt8(data, array[i])) {
61             CODEC_LOGE("write array[i] failed!");
62             return HDF_ERR_INVALID_PARAM;
63         }
64     }
65     return HDF_SUCCESS;
66 }
67 
WriteEventInfo(struct HdfSBuf * data,struct EventInfo * info)68 static int32_t WriteEventInfo(struct HdfSBuf *data, struct EventInfo *info)
69 {
70     if (info == NULL) {
71         CODEC_LOGE("invalid parameter");
72         return HDF_ERR_INVALID_PARAM;
73     }
74     if (!HdfSbufWriteInt64(data, info->appData)) {
75         CODEC_LOGE("write appData failed!");
76         return HDF_ERR_INVALID_PARAM;
77     }
78 
79     if (!HdfSbufWriteUint32(data, info->data1)) {
80         CODEC_LOGE("write data1 failed!");
81         return HDF_ERR_INVALID_PARAM;
82     }
83 
84     if (!HdfSbufWriteUint32(data, info->data2)) {
85         CODEC_LOGE("write data2 failed!");
86         return HDF_ERR_INVALID_PARAM;
87     }
88 
89     int32_t ret = WriteArray(data, info->eventData, info->eventDataLen);
90     if (ret != HDF_SUCCESS) {
91         CODEC_LOGE("write eventData failed!");
92     }
93     return ret;
94 }
95 
CodecCallbackTypeProxyEventHandler(struct CodecCallbackType * self,enum OMX_EVENTTYPE event,struct EventInfo * info)96 static int32_t CodecCallbackTypeProxyEventHandler(struct CodecCallbackType *self, enum OMX_EVENTTYPE event,
97                                                   struct EventInfo *info)
98 {
99     if (self == NULL) {
100         CODEC_LOGE("invalid parameter");
101         return HDF_ERR_INVALID_PARAM;
102     }
103     int32_t ret;
104 
105     struct HdfSBuf *data = HdfSbufTypedObtain(SBUF_IPC);
106     struct HdfSBuf *reply = HdfSbufTypedObtain(SBUF_IPC);
107     if (data == NULL || reply == NULL) {
108         CODEC_LOGE("HdfSubf malloc failed!");
109         ReleaseSbuf(data, reply);
110         return HDF_ERR_MALLOC_FAIL;
111     }
112 
113     if (!HdfRemoteServiceWriteInterfaceToken(self->remote, data)) {
114         CODEC_LOGE("write interface token failed");
115         ReleaseSbuf(data, reply);
116         return HDF_FAILURE;
117     }
118 
119     if (!HdfSbufWriteUint32(data, (uint32_t)event)) {
120         CODEC_LOGE("write event failed!");
121         ReleaseSbuf(data, reply);
122         return HDF_ERR_INVALID_PARAM;
123     }
124 
125     ret = WriteEventInfo(data, info);
126     if (ret != HDF_SUCCESS) {
127         CODEC_LOGE("write event info failed");
128         ReleaseSbuf(data, reply);
129         return HDF_ERR_INVALID_PARAM;
130     }
131 
132     ret = CodecCallbackTypeProxyCall(self, CMD_EVENT_HANDLER, data, reply);
133     if (ret != HDF_SUCCESS) {
134         CODEC_LOGE("call failed! error code is %{public}d", ret);
135         ReleaseSbuf(data, reply);
136         return ret;
137     }
138 
139     ReleaseSbuf(data, reply);
140     return ret;
141 }
142 
CodecCallbackTypeProxyEmptyBufferDone(struct CodecCallbackType * self,int64_t appData,const struct OmxCodecBuffer * buffer)143 static int32_t CodecCallbackTypeProxyEmptyBufferDone(struct CodecCallbackType *self, int64_t appData,
144                                                      const struct OmxCodecBuffer *buffer)
145 {
146     if (self == NULL) {
147         CODEC_LOGE("invalid parameter");
148         return HDF_ERR_INVALID_PARAM;
149     }
150     int32_t ret;
151 
152     struct HdfSBuf *data = HdfSbufTypedObtain(SBUF_IPC);
153     struct HdfSBuf *reply = HdfSbufTypedObtain(SBUF_IPC);
154     if (data == NULL || reply == NULL) {
155         CODEC_LOGE("HdfSubf malloc failed!");
156         ReleaseSbuf(data, reply);
157         return HDF_ERR_MALLOC_FAIL;
158     }
159 
160     if (!HdfRemoteServiceWriteInterfaceToken(self->remote, data)) {
161         CODEC_LOGE("write interface token failed");
162         ReleaseSbuf(data, reply);
163         return HDF_FAILURE;
164     }
165 
166     if (!HdfSbufWriteInt64(data, appData)) {
167         CODEC_LOGE("write appData failed!");
168         ReleaseSbuf(data, reply);
169         return HDF_ERR_INVALID_PARAM;
170     }
171     if (!OmxCodecBufferBlockMarshalling(data, buffer)) {
172         CODEC_LOGE("write buffer failed!");
173         ReleaseSbuf(data, reply);
174         return HDF_ERR_INVALID_PARAM;
175     }
176 
177     ret = CodecCallbackTypeProxyCall(self, CMD_EMPTY_BUFFER_DONE, data, reply);
178     if (ret != HDF_SUCCESS) {
179         CODEC_LOGE("call failed! error code is %{public}d", ret);
180         ReleaseSbuf(data, reply);
181         return ret;
182     }
183 
184     ReleaseSbuf(data, reply);
185     return ret;
186 }
187 
CodecCallbackTypeProxyFillBufferDone(struct CodecCallbackType * self,int64_t appData,const struct OmxCodecBuffer * buffer)188 static int32_t CodecCallbackTypeProxyFillBufferDone(struct CodecCallbackType *self, int64_t appData,
189                                                     const struct OmxCodecBuffer *buffer)
190 {
191     if (self == NULL) {
192         CODEC_LOGE("invalid parameter");
193         return HDF_ERR_INVALID_PARAM;
194     }
195     int32_t ret;
196 
197     struct HdfSBuf *data = HdfSbufTypedObtain(SBUF_IPC);
198     struct HdfSBuf *reply = HdfSbufTypedObtain(SBUF_IPC);
199     if (data == NULL || reply == NULL) {
200         CODEC_LOGE("HdfSubf malloc failed!");
201         ReleaseSbuf(data, reply);
202         return HDF_ERR_MALLOC_FAIL;
203     }
204 
205     if (!HdfRemoteServiceWriteInterfaceToken(self->remote, data)) {
206         CODEC_LOGE("write interface token failed");
207         ReleaseSbuf(data, reply);
208         return HDF_FAILURE;
209     }
210 
211     if (!HdfSbufWriteInt64(data, appData)) {
212         CODEC_LOGE("write appData failed!");
213         ReleaseSbuf(data, reply);
214         return HDF_ERR_INVALID_PARAM;
215     }
216     if (!OmxCodecBufferBlockMarshalling(data, buffer)) {
217         CODEC_LOGE("write buffer failed!");
218         ReleaseSbuf(data, reply);
219         return HDF_ERR_INVALID_PARAM;
220     }
221 
222     ret = CodecCallbackTypeProxyCall(self, CMD_FILL_BUFFER_DONE, data, reply);
223     if (ret != HDF_SUCCESS) {
224         CODEC_LOGE("call failed! error code is %{public}d", ret);
225         ReleaseSbuf(data, reply);
226         return ret;
227     }
228 
229     ReleaseSbuf(data, reply);
230     return ret;
231 }
232 
CodecCallbackTypeProxyConstruct(struct CodecCallbackType * instance)233 static void CodecCallbackTypeProxyConstruct(struct CodecCallbackType *instance)
234 {
235     if (instance == NULL) {
236         CODEC_LOGE("invalid parameter");
237         return;
238     }
239     instance->EventHandler = CodecCallbackTypeProxyEventHandler;
240     instance->EmptyBufferDone = CodecCallbackTypeProxyEmptyBufferDone;
241     instance->FillBufferDone = CodecCallbackTypeProxyFillBufferDone;
242 }
243 
CodecCallbackTypeGet(struct HdfRemoteService * remote)244 struct CodecCallbackType *CodecCallbackTypeGet(struct HdfRemoteService *remote)
245 {
246     if (remote == NULL) {
247         CODEC_LOGE("remote is null");
248         return NULL;
249     }
250 
251     struct CodecCallbackType *instance = (struct CodecCallbackType *)OsalMemAlloc(sizeof(struct CodecCallbackType));
252     if (instance == NULL) {
253         CODEC_LOGE("OsalMemAlloc failed!");
254         return NULL;
255     }
256 
257     if (!HdfRemoteServiceSetInterfaceDesc(remote, "ohos.hdi.codec_service")) {
258         OsalMemFree(instance);
259         CODEC_LOGE("failed to init interface desc");
260         return NULL;
261     }
262 
263     instance->remote = remote;
264     CodecCallbackTypeProxyConstruct(instance);
265     return instance;
266 }
267 
CodecCallbackTypeRelease(struct CodecCallbackType * instance)268 void CodecCallbackTypeRelease(struct CodecCallbackType *instance)
269 {
270     if (instance == NULL) {
271         CODEC_LOGE("instance is null");
272         return;
273     }
274     if (instance->remote != NULL) {
275         HdfRemoteServiceRecycle(instance->remote);
276         instance->remote = NULL;
277     }
278     OsalMemFree(instance);
279 }
280