• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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_service.h"
17 #include <errno.h>
18 #include <fcntl.h>
19 #include <securec.h>
20 #include <stdio.h>
21 #include <sys/mman.h>
22 #include <unistd.h>
23 #include "ashmem_wrapper.h"
24 #ifndef CODEC_HAL_PASSTHROUGH
25 #include "codec_config_parser.h"
26 #endif
27 #include "hdf_log.h"
28 #include "osal_mem.h"
29 
30 #define HDF_LOG_TAG codec_hdi_service
31 #define VIDEO_HARDWARE_ENCODER_INDEX 0
32 #define VIDEO_HARDWARE_DECODER_INDEX 1
33 #define AUDIO_HARDWARE_ENCODER_INDEX 4
34 #define AUDIO_HARDWARE_DECODER_INDEX 5
35 
36 struct CodecInstance *g_codecInstance = NULL;
37 #ifdef CODEC_HAL_PASSTHROUGH
38 const CodecCallback *g_codecCallback = NULL;
39 UINTPTR g_userData;
40 #endif
41 
DefaultCbOnEvent(UINTPTR userData,EventType event,uint32_t length,int32_t eventData[])42 static int32_t DefaultCbOnEvent(UINTPTR userData, EventType event, uint32_t length, int32_t eventData[])
43 {
44 #ifdef CODEC_HAL_PASSTHROUGH
45     g_codecCallback->OnEvent(g_userData, event, length, eventData);
46 #endif
47     return HDF_SUCCESS;
48 }
49 
DefaultCbInputBufferAvailable(UINTPTR userData,CodecBuffer * inBuf,int32_t * acquireFd)50 static int32_t DefaultCbInputBufferAvailable(UINTPTR userData, CodecBuffer *inBuf, int32_t *acquireFd)
51 {
52     if (inBuf == NULL || inBuf->bufferCnt == 0) {
53         HDF_LOGE("%{public}s: inBuf Nullpoint or buf not assigned", __func__);
54         return HDF_FAILURE;
55     }
56     CodecBuffer *inputInfo = GetInputInfo(g_codecInstance, inBuf->bufferId);
57     if (inputInfo == NULL || inputInfo->bufferCnt == 0) {
58         HDF_LOGE("%{public}s: inputInfo Nullpoint or buf not assigned", __func__);
59         return HDF_FAILURE;
60     }
61     CopyCodecBufferWithTypeSwitch(g_codecInstance, inputInfo, inBuf, true);
62     EmptyCodecBuffer(inputInfo);
63     g_codecInstance->bufferManagerWrapper->PutUsedInputDataBuffer(g_codecInstance->bufferManagerWrapper, inputInfo);
64 #ifdef CODEC_HAL_PASSTHROUGH
65     g_codecCallback->InputBufferAvailable(g_userData, inBuf, acquireFd);
66 #endif
67     return HDF_SUCCESS;
68 }
69 
DefaultCbOutputBufferAvailable(UINTPTR userData,CodecBuffer * outBuf,int32_t * acquireFd)70 static int32_t DefaultCbOutputBufferAvailable(UINTPTR userData, CodecBuffer *outBuf, int32_t *acquireFd)
71 {
72     if (outBuf == NULL || outBuf->bufferCnt == 0) {
73         HDF_LOGE("%{public}s: outBuf Nullpoint or buf not assigned", __func__);
74         return HDF_FAILURE;
75     }
76     struct BufferManagerWrapper *bmWrapper = g_codecInstance->bufferManagerWrapper;
77     CodecBuffer *outputInfo = GetOutputInfo(g_codecInstance, outBuf->bufferId);
78     if (outputInfo == NULL || outputInfo->bufferCnt == 0) {
79         HDF_LOGE("%{public}s: outputInfo Nullpoint or buf not assigned", __func__);
80         return HDF_FAILURE;
81     }
82     CopyCodecBufferWithTypeSwitch(g_codecInstance, outputInfo, outBuf, true);
83     bmWrapper->PutOutputDataBuffer(bmWrapper, outputInfo);
84 #ifdef CODEC_HAL_PASSTHROUGH
85     g_codecCallback->OutputBufferAvailable(g_userData, outputInfo, acquireFd);
86 #endif
87     // get a new OutputBuffer
88     CodecBuffer *output = NULL;
89     while (output == NULL && g_codecInstance->codecStatus == CODEC_STATUS_STARTED) {
90         output = bmWrapper->GetUsedOutputDataBuffer(bmWrapper, QUEUE_TIME_OUT);
91     }
92     if (output == NULL) {
93         HDF_LOGE("%{public}s: output is NULL", __func__);
94         return HDF_FAILURE;
95     }
96     SetOemCodecBufferType(outBuf, output);
97     CopyCodecBufferWithTypeSwitch(g_codecInstance, outBuf, output, false);
98 
99     return HDF_SUCCESS;
100 }
101 
CodecInit()102 int32_t CodecInit()
103 {
104     g_codecInstance = GetCodecInstance();
105     if (g_codecInstance == NULL) {
106         HDF_LOGE("%{public}s: g_codecInstance is NULL!", __func__);
107         return HDF_FAILURE;
108     }
109     int32_t ret = InitCodecInstance(g_codecInstance);
110     if (ret != HDF_SUCCESS) {
111         HDF_LOGE("%{public}s: InitCodecInstance failed!", __func__);
112         return ret;
113     }
114 
115     if (g_codecInstance->codecOemIface == NULL) {
116         HDF_LOGE("%{public}s: oemIface is NULL!", __func__);
117         return HDF_FAILURE;
118     }
119     return g_codecInstance->codecOemIface->codecInit();
120 }
121 
CodecDeinit()122 int32_t CodecDeinit()
123 {
124     if (g_codecInstance == NULL || g_codecInstance->codecOemIface == NULL) {
125         HDF_LOGE("%{public}s: g_codecInstance or oemIface is NULL!", __func__);
126         return HDF_FAILURE;
127     }
128     g_codecInstance->codecOemIface->codecDeinit();
129     int32_t ret = DestroyCodecInstance(g_codecInstance);
130     if (ret != HDF_SUCCESS) {
131         HDF_LOGE("%{public}s: CodecDeinit failed!", __func__);
132         return ret;
133     }
134     g_codecInstance = NULL;
135     return HDF_SUCCESS;
136 }
137 
CodecEnumerateCapability(uint32_t index,CodecCapability * cap)138 int32_t CodecEnumerateCapability(uint32_t index, CodecCapability *cap)
139 {
140 #ifndef CODEC_HAL_PASSTHROUGH
141     int32_t loopIndex;
142     uint32_t cursor = index;
143     CodecCapablityGroup *group = NULL;
144     if (cursor + 1 < cursor) {
145         HDF_LOGE("%{public}s: the index out of bounds!", __func__);
146         return HDF_FAILURE;
147     }
148     for (loopIndex = 0; loopIndex < CODEC_CAPABLITY_GROUP_NUM; loopIndex++) {
149         group = GetCapablityGroup(loopIndex);
150         if (group == NULL) {
151             continue;
152         }
153         if (cursor + 1 <= (uint32_t)group->num) {
154             *cap = group->capablitis[cursor];
155             return HDF_SUCCESS;
156         } else {
157             cursor -= group->num;
158         }
159     }
160 #endif
161     return HDF_FAILURE;
162 }
163 
CodecGetCapability(AvCodecMime mime,CodecType type,uint32_t flags,CodecCapability * cap)164 int32_t CodecGetCapability(AvCodecMime mime, CodecType type, uint32_t flags, CodecCapability *cap)
165 {
166 #ifndef CODEC_HAL_PASSTHROUGH
167     int32_t groupIndex;
168     int32_t capIndex;
169     CodecCapablityGroup *group = NULL;
170     CodecCapability *capItem;
171     bool inputHardwareFlag = flags == 0;
172 
173     for (groupIndex = 0; groupIndex < CODEC_CAPABLITY_GROUP_NUM; groupIndex++) {
174         group = GetCapablityGroup(groupIndex);
175         if (group == NULL) {
176             continue;
177         }
178         bool curHardwareFlag = (groupIndex == VIDEO_HARDWARE_ENCODER_INDEX)
179             || (groupIndex == VIDEO_HARDWARE_DECODER_INDEX) || (groupIndex == AUDIO_HARDWARE_ENCODER_INDEX)
180             || (groupIndex == AUDIO_HARDWARE_DECODER_INDEX);
181         if (inputHardwareFlag != curHardwareFlag) {
182             continue;
183         }
184         for (capIndex = 0; capIndex < group->num; capIndex++) {
185             capItem = &group->capablitis[capIndex];
186             if (mime == capItem->mime && type == capItem->type) {
187                 *cap = group->capablitis[capIndex];
188                 return HDF_SUCCESS;
189             }
190         }
191     }
192 #endif
193     return HDF_FAILURE;
194 }
195 
CodecCreate(const char * name,CODEC_HANDLETYPE * handle)196 int32_t CodecCreate(const char* name, CODEC_HANDLETYPE *handle)
197 {
198     if (g_codecInstance == NULL || g_codecInstance->codecOemIface == NULL) {
199         HDF_LOGE("%{public}s: g_codecInstance or oemIface is NULL!", __func__);
200         return HDF_FAILURE;
201     }
202     int32_t ret = g_codecInstance->codecOemIface->codecCreate(name, handle);
203     if (ret != HDF_SUCCESS) {
204         return ret;
205     }
206     g_codecInstance->handle = *handle;
207     HDF_LOGI("%{public}s codec created", __func__);
208     return HDF_SUCCESS;
209 }
210 
CodecCreateByType(CodecType type,AvCodecMime mime,CODEC_HANDLETYPE * handle)211 int32_t CodecCreateByType(CodecType type, AvCodecMime mime, CODEC_HANDLETYPE *handle)
212 {
213     (void)type;
214     (void)mime;
215     (void)handle;
216     return HDF_ERR_NOT_SUPPORT;
217 }
218 
CodecDestroy(CODEC_HANDLETYPE handle)219 int32_t CodecDestroy(CODEC_HANDLETYPE handle)
220 {
221     if (g_codecInstance == NULL || g_codecInstance->codecOemIface == NULL) {
222         HDF_LOGE("%{public}s: g_codecInstance or oemIface is NULL!", __func__);
223         return HDF_FAILURE;
224     }
225     return g_codecInstance->codecOemIface->codecDestroy(handle);
226 }
227 
CodecSetPortMode(CODEC_HANDLETYPE handle,DirectionType direct,AllocateBufferMode mode,BufferType type)228 int32_t CodecSetPortMode(CODEC_HANDLETYPE handle, DirectionType direct, AllocateBufferMode mode, BufferType type)
229 {
230     (void)handle;
231     (void)direct;
232     (void)mode;
233     (void)type;
234     return HDF_ERR_NOT_SUPPORT;
235 }
236 
CodecGetPortMode(CODEC_HANDLETYPE handle,DirectionType direct,AllocateBufferMode * mode,BufferType * type)237 int32_t CodecGetPortMode(CODEC_HANDLETYPE handle, DirectionType direct, AllocateBufferMode *mode, BufferType *type)
238 {
239     (void)handle;
240     (void)direct;
241     (void)mode;
242     (void)type;
243     return HDF_ERR_NOT_SUPPORT;
244 }
245 
CodecSetParameter(CODEC_HANDLETYPE handle,const Param * params,int32_t paramCnt)246 int32_t CodecSetParameter(CODEC_HANDLETYPE handle, const Param *params, int32_t paramCnt)
247 {
248     if (g_codecInstance == NULL || g_codecInstance->codecOemIface == NULL) {
249         HDF_LOGE("%{public}s: g_codecInstance or oemIface is NULL!", __func__);
250         return HDF_FAILURE;
251     }
252     if (params == NULL || paramCnt <= 0) {
253         HDF_LOGE("%{public}s: params empty!", __func__);
254         return HDF_FAILURE;
255     }
256     for (int32_t i = 0; i < paramCnt; i++) {
257         if (params[i].key == KEY_CODEC_TYPE) {
258             int32_t codecType = 0;
259             memcpy_s(&codecType, sizeof(codecType), params[i].val, params[i].size);
260             g_codecInstance->codecType = codecType;
261         }
262     }
263     return g_codecInstance->codecOemIface->codecSetParameter(handle, params, paramCnt);
264 }
265 
CodecGetParameter(CODEC_HANDLETYPE handle,Param * params,int32_t paramCnt)266 int32_t CodecGetParameter(CODEC_HANDLETYPE handle, Param *params, int32_t paramCnt)
267 {
268     if (g_codecInstance == NULL || g_codecInstance->codecOemIface == NULL) {
269         HDF_LOGE("%{public}s: g_codecInstance or oemIface is NULL!", __func__);
270         return HDF_FAILURE;
271     }
272     if (params == NULL || paramCnt <= 0) {
273         HDF_LOGE("%{public}s: params empty!", __func__);
274         return HDF_FAILURE;
275     }
276     return g_codecInstance->codecOemIface->codecGetParameter(handle, params, paramCnt);
277 }
278 
CodecStart(CODEC_HANDLETYPE handle)279 int32_t CodecStart(CODEC_HANDLETYPE handle)
280 {
281     if (g_codecInstance == NULL || g_codecInstance->codecOemIface == NULL) {
282         HDF_LOGE("%{public}s: g_codecInstance or oemIface is NULL!", __func__);
283         return HDF_FAILURE;
284     }
285     if (!g_codecInstance->hasCallback) {
286         g_codecInstance->defaultCb.OnEvent = DefaultCbOnEvent;
287         g_codecInstance->defaultCb.InputBufferAvailable = DefaultCbInputBufferAvailable;
288         g_codecInstance->defaultCb.OutputBufferAvailable = DefaultCbOutputBufferAvailable;
289         g_codecInstance->codecOemIface->codecSetCallback(handle, &(g_codecInstance->defaultCb), 0);
290     }
291     return RunCodecInstance(g_codecInstance);
292 }
293 
CodecStop(CODEC_HANDLETYPE handle)294 int32_t CodecStop(CODEC_HANDLETYPE handle)
295 {
296     if (g_codecInstance == NULL) {
297         HDF_LOGE("%{public}s: g_codecInstance is NULL!", __func__);
298         return HDF_FAILURE;
299     }
300     return StopCodecInstance(g_codecInstance);
301 }
302 
CodecReset(CODEC_HANDLETYPE handle)303 int32_t CodecReset(CODEC_HANDLETYPE handle)
304 {
305     (void)handle;
306     return HDF_ERR_NOT_SUPPORT;
307 }
308 
CodecFlush(CODEC_HANDLETYPE handle,DirectionType directType)309 int32_t CodecFlush(CODEC_HANDLETYPE handle, DirectionType directType)
310 {
311     if (g_codecInstance == NULL || g_codecInstance->codecOemIface == NULL) {
312         HDF_LOGE("%{public}s: g_codecInstance or oemIface is NULL!", __func__);
313         return HDF_FAILURE;
314     }
315     return g_codecInstance->codecOemIface->codecFlush(handle, directType);
316 }
317 
CodecQueueInput(CODEC_HANDLETYPE handle,const CodecBuffer * inputData,uint32_t timeoutMs,int releaseFenceFd)318 int32_t CodecQueueInput(CODEC_HANDLETYPE handle, const CodecBuffer *inputData, uint32_t timeoutMs, int releaseFenceFd)
319 {
320     if (g_codecInstance == NULL) {
321         HDF_LOGE("%{public}s: g_codecInstance is NULL!", __func__);
322         return HDF_FAILURE;
323     }
324 
325     if (g_codecInstance->codecStatus == CODEC_STATUS_IDLE) {
326         if (g_codecInstance->codecType != VIDEO_DECODER && g_codecInstance->codecType != AUDIO_DECODER &&
327             g_codecInstance->codecType != VIDEO_ENCODER && g_codecInstance->codecType != AUDIO_ENCODER) {
328             HDF_LOGE("%{public}s: codecType invalid, queue input buffer failed!", __func__);
329             return HDF_FAILURE;
330         }
331         for (uint32_t i = 0; i < inputData->bufferCnt; i++) {
332             if (AddInputShm(g_codecInstance, &inputData->buffer[i], inputData->bufferId) != HDF_SUCCESS) {
333                 HDF_LOGE("%{public}s: AddInputShm failed, queue input buffer failed!", __func__);
334                 return HDF_FAILURE;
335             }
336         }
337         CodecBuffer *dup = DupCodecBuffer(inputData);
338         if (AddInputInfo(g_codecInstance, dup) != HDF_SUCCESS) {
339             HDF_LOGE("%{public}s: AddInputInfo failed, queue input buffer failed!", __func__);
340             return HDF_FAILURE;
341         }
342         g_codecInstance->bufferManagerWrapper->PutUsedInputDataBuffer(g_codecInstance->bufferManagerWrapper, dup);
343         return HDF_SUCCESS;
344     } else if (g_codecInstance->codecStatus == CODEC_STATUS_STARTED) {
345         CodecBuffer *info = GetInputInfo(g_codecInstance, inputData->bufferId);
346         CopyCodecBufferWithTypeSwitch(g_codecInstance, info, inputData, true);
347         g_codecInstance->bufferManagerWrapper->PutInputDataBuffer(g_codecInstance->bufferManagerWrapper, info);
348         return HDF_SUCCESS;
349     }
350     return HDF_SUCCESS;
351 }
352 
CodecDequeueInput(CODEC_HANDLETYPE handle,uint32_t timeoutMs,int32_t * acquireFd,CodecBuffer * inputData)353 int32_t CodecDequeueInput(CODEC_HANDLETYPE handle, uint32_t timeoutMs, int32_t *acquireFd, CodecBuffer *inputData)
354 {
355     if (g_codecInstance == NULL) {
356         HDF_LOGE("%{public}s: g_codecInstance is NULL!", __func__);
357         return HDF_FAILURE;
358     }
359 
360     CodecBuffer *info = g_codecInstance->bufferManagerWrapper->GetUsedInputDataBuffer(
361         g_codecInstance->bufferManagerWrapper, timeoutMs);
362     if (info != NULL) {
363         *acquireFd = -1;
364         inputData->buffer[0].type = info->buffer[0].type;
365         CopyCodecBufferWithTypeSwitch(g_codecInstance, inputData, info, false);
366     } else {
367         return HDF_ERR_TIMEOUT;
368     }
369 
370     return HDF_SUCCESS;
371 }
372 
CodecQueueOutput(CODEC_HANDLETYPE handle,CodecBuffer * outInfo,uint32_t timeoutMs,int releaseFenceFd)373 int32_t CodecQueueOutput(CODEC_HANDLETYPE handle, CodecBuffer *outInfo, uint32_t timeoutMs, int releaseFenceFd)
374 {
375     if (g_codecInstance == NULL || g_codecInstance->bufferManagerWrapper == NULL) {
376         HDF_LOGE("%{public}s: g_codecInstance or buffermanager is NULL!", __func__);
377         return HDF_FAILURE;
378     }
379 
380     if (g_codecInstance->codecStatus == CODEC_STATUS_IDLE) {
381         if (g_codecInstance->codecType != VIDEO_DECODER && g_codecInstance->codecType != AUDIO_DECODER &&
382             g_codecInstance->codecType != VIDEO_ENCODER && g_codecInstance->codecType != AUDIO_ENCODER) {
383             HDF_LOGE("%{public}s: codecType invalid, queue output buffer failed!", __func__);
384             return HDF_FAILURE;
385         }
386         for (uint32_t i = 0; i < outInfo->bufferCnt; i++) {
387             if (AddOutputShm(g_codecInstance, &outInfo->buffer[i], outInfo->bufferId) != HDF_SUCCESS) {
388                 HDF_LOGE("%{public}s: AddOutputShm failed, queue output buffer failed!", __func__);
389             }
390         }
391         CodecBuffer *dup = DupCodecBuffer(outInfo);
392         if (AddOutputInfo(g_codecInstance, dup) != HDF_SUCCESS) {
393             HDF_LOGE("%{public}s: AddOutputInfo failed, queue output buffer failed!", __func__);
394             return HDF_FAILURE;
395         }
396         g_codecInstance->bufferManagerWrapper->PutUsedOutputDataBuffer(g_codecInstance->bufferManagerWrapper, dup);
397         return HDF_SUCCESS;
398     } else if (g_codecInstance->codecStatus == CODEC_STATUS_STARTED) {
399         CodecBuffer *info = GetOutputInfo(g_codecInstance, outInfo->bufferId);
400         CopyCodecBufferWithTypeSwitch(g_codecInstance, info, outInfo, true);
401         EmptyCodecBuffer(info);
402         g_codecInstance->bufferManagerWrapper->PutUsedOutputDataBuffer(g_codecInstance->bufferManagerWrapper, info);
403         return HDF_SUCCESS;
404     } else if (g_codecInstance->codecStatus == CODEC_STATUS_STOPED) {
405         CodecBuffer *dup = DupCodecBuffer(outInfo);
406         g_codecInstance->bufferManagerWrapper->PutOutputDataBuffer(g_codecInstance->bufferManagerWrapper, dup);
407     }
408     return HDF_SUCCESS;
409 }
410 
CodecDequeueOutput(CODEC_HANDLETYPE handle,uint32_t timeoutMs,int32_t * acquireFd,CodecBuffer * outInfo)411 int32_t CodecDequeueOutput(CODEC_HANDLETYPE handle, uint32_t timeoutMs, int32_t *acquireFd, CodecBuffer *outInfo)
412 {
413     if (g_codecInstance == NULL || g_codecInstance->bufferManagerWrapper == NULL) {
414         HDF_LOGE("%{public}s: g_codecInstance or buffermanager is NULL!", __func__);
415         return HDF_FAILURE;
416     }
417 
418     CodecBuffer *info = g_codecInstance->bufferManagerWrapper->GetOutputDataBuffer(
419         g_codecInstance->bufferManagerWrapper, timeoutMs);
420     if (info != NULL) {
421         *acquireFd = -1;
422         outInfo->buffer[0].type = info->buffer[0].type;
423         CopyCodecBufferWithTypeSwitch(g_codecInstance, outInfo, info, false);
424     } else {
425         return HDF_ERR_TIMEOUT;
426     }
427 
428     return HDF_SUCCESS;
429 }
430 
CodecSetCallback(CODEC_HANDLETYPE handle,const CodecCallback * cb,UINTPTR instance)431 int32_t CodecSetCallback(CODEC_HANDLETYPE handle, const CodecCallback *cb, UINTPTR instance)
432 {
433     if (g_codecInstance == NULL || g_codecInstance->codecOemIface == NULL) {
434         HDF_LOGE("%{public}s: g_codecInstance or oemIface is NULL!", __func__);
435         return HDF_FAILURE;
436     }
437 #ifndef CODEC_HAL_PASSTHROUGH
438     int32_t ret = g_codecInstance->codecOemIface->codecSetCallback(handle, cb, instance);
439 #else
440     g_codecInstance->defaultCb.OnEvent = DefaultCbOnEvent;
441     g_codecInstance->defaultCb.InputBufferAvailable = DefaultCbInputBufferAvailable;
442     g_codecInstance->defaultCb.OutputBufferAvailable = DefaultCbOutputBufferAvailable;
443     int32_t ret = g_codecInstance->codecOemIface->codecSetCallback(handle, &(g_codecInstance->defaultCb), 0);
444     g_codecCallback = cb;
445     g_userData = instance;
446 #endif
447     if (ret == HDF_SUCCESS) {
448         g_codecInstance->hasCallback = true;
449     }
450     return ret;
451 }
452