• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_instance.h"
17 #include <buffer_handle_utils.h>
18 #include <dlfcn.h>
19 #include <securec.h>
20 #include "hdf_log.h"
21 #include "osal_mem.h"
22 
23 #define HDF_LOG_TAG codec_hdi_instance
24 
25 #define CODEC_OEM_INTERFACE_LIB_NAME    "libcodec_oem_interface.z.so"
26 #define BUFFER_COUNT                    1
27 
InitData(CodecBuffer ** inputData,CodecBuffer ** outputData)28 static bool InitData(CodecBuffer **inputData, CodecBuffer **outputData)
29 {
30     if (inputData == NULL || outputData == NULL) {
31         HDF_LOGE("%{public}s: inputData or outputData NULL!", __func__);
32         return false;
33     }
34     int32_t codecBufferSize = sizeof(CodecBuffer) + sizeof(CodecBufferInfo) * BUFFER_COUNT;
35     *inputData = (CodecBuffer *)OsalMemCalloc(codecBufferSize);
36     if (*inputData == NULL) {
37         HDF_LOGE("%{public}s: inputData is NULL!", __func__);
38         return false;
39     }
40     *outputData = (CodecBuffer *)OsalMemCalloc(codecBufferSize);
41     if (*outputData == NULL) {
42         OsalMemFree(*inputData);
43         *inputData = NULL;
44         HDF_LOGE("%{public}s: outputData is NULL!", __func__);
45         return false;
46     }
47     return true;
48 }
49 
WaitForOutputDataBuffer(struct CodecInstance * instance,CodecBuffer * outputData)50 static int32_t WaitForOutputDataBuffer(struct CodecInstance *instance, CodecBuffer *outputData)
51 {
52     struct BufferManagerWrapper *bmWrapper = instance->bufferManagerWrapper;
53     CodecBuffer *output = NULL;
54     while (instance->codecStatus == CODEC_STATUS_STARTED) {
55         if (bmWrapper->IsInputDataBufferReady(bmWrapper, QUEUE_TIME_OUT)
56             && bmWrapper->IsUsedOutputDataBufferReady(bmWrapper, QUEUE_TIME_OUT)) {
57             output = bmWrapper->GetUsedOutputDataBuffer(bmWrapper, QUEUE_TIME_OUT);
58             if (output == NULL) {
59                 continue;
60             }
61             if (!SetOemCodecBufferType(outputData, output)) {
62                 HDF_LOGE("%{public}s: SetOemCodecBufferType failed!", __func__);
63                 return HDF_FAILURE;
64             }
65             if (!CopyCodecBufferWithTypeSwitch(instance, outputData, output, false)) {
66                 HDF_LOGE("%{public}s: CopyCodecBuffer failed!", __func__);
67                 return HDF_FAILURE;
68             }
69             break;
70         }
71     }
72     return HDF_SUCCESS;
73 }
74 
PrepareInputDataBuffer(struct BufferManagerWrapper * bmWrapper,struct CodecInstance * instance,CodecBuffer * bufferToOemCodec)75 static int32_t PrepareInputDataBuffer(struct BufferManagerWrapper *bmWrapper,
76     struct CodecInstance *instance, CodecBuffer *bufferToOemCodec)
77 {
78     if (!bmWrapper->IsInputDataBufferReady(bmWrapper, QUEUE_TIME_OUT)) {
79         return HDF_ERR_TIMEOUT;
80     }
81     CodecBuffer *bufferInQueue = bmWrapper->GetInputDataBuffer(bmWrapper, QUEUE_TIME_OUT);
82     if (bufferInQueue == NULL) {
83         return HDF_ERR_TIMEOUT;
84     }
85 
86     if (!SetOemCodecBufferType(bufferToOemCodec, bufferInQueue)) {
87         HDF_LOGE("%{public}s: SetOemCodecBufferType failed!", __func__);
88         return HDF_FAILURE;
89     }
90     if (!CopyCodecBufferWithTypeSwitch(instance, bufferToOemCodec, bufferInQueue, false)) {
91         HDF_LOGE("%{public}s: CopyCodecBuffer failed!", __func__);
92         return HDF_FAILURE;
93     }
94     return HDF_SUCCESS;
95 }
96 
CodecTaskThread(void * arg)97 static void *CodecTaskThread(void *arg)
98 {
99     if (arg == NULL) {
100         HDF_LOGE("%{public}s: Invalid arg, exit CodecTaskThread!", __func__);
101         return NULL;
102     }
103     struct CodecInstance *instance = (struct CodecInstance *)arg;
104     struct BufferManagerWrapper *bmWrapper = instance->bufferManagerWrapper;
105     if (bmWrapper == NULL) {
106         HDF_LOGE("%{public}s: BufferManager not ready!", __func__);
107         return NULL;
108     }
109     HDF_LOGI("%{public}s: codec task thread started!", __func__);
110 
111     CodecBuffer *inputData = NULL;
112     CodecBuffer *outputData = NULL;
113     int32_t ret = HDF_FAILURE;
114     if (!InitData(&inputData, &outputData)) {
115         HDF_LOGE("%{public}s: InitData failed!", __func__);
116         return NULL;
117     }
118 
119     inputData->bufferCnt = BUFFER_COUNT;
120     outputData->bufferCnt = BUFFER_COUNT;
121     if (WaitForOutputDataBuffer(instance, outputData) != HDF_SUCCESS) {
122         OsalMemFree(inputData);
123         OsalMemFree(outputData);
124         HDF_LOGE("%{public}s: WaitForOutputDataBuffer failed!", __func__);
125         return NULL;
126     }
127     while (instance->codecStatus == CODEC_STATUS_STARTED) {
128         if (PrepareInputDataBuffer(bmWrapper, instance, inputData) != HDF_SUCCESS) {
129             continue;
130         }
131 
132         if (instance->codecType == VIDEO_DECODER) {
133             ret = instance->codecOemIface->codecDecode(instance->handle, inputData, outputData, QUEUE_TIME_OUT);
134         } else if (instance->codecType == VIDEO_ENCODER) {
135             ret = instance->codecOemIface->codecEncode(instance->handle, inputData, outputData, QUEUE_TIME_OUT);
136         }
137         if (ret == HDF_SUCCESS || (outputData->flag & STREAM_FLAG_EOS)) {
138             HDF_LOGI("%{public}s: output reach STREAM_FLAG_EOS!", __func__);
139             break;
140         }
141     }
142     OsalMutexLock(&instance->codecStatusLock);
143     instance->codecStatus = CODEC_STATUS_STOPPED;
144     pthread_cond_signal(&instance->codecStatusCond);
145     OsalMutexUnlock(&instance->codecStatusLock);
146 
147     OsalMemFree(inputData);
148     OsalMemFree(outputData);
149     HDF_LOGI("%{public}s: codec task thread finished!", __func__);
150     return NULL;
151 }
152 
GetUsedInputInfo(struct CodecInstance * instance,CodecBuffer * inputInfoSendToClient)153 static int32_t GetUsedInputInfo(struct CodecInstance *instance, CodecBuffer *inputInfoSendToClient)
154 {
155     if (instance == NULL || instance->bufferManagerWrapper == NULL || inputInfoSendToClient == NULL) {
156         HDF_LOGE("%{public}s failed: invalid parameter!", __func__);
157         return HDF_FAILURE;
158     }
159 
160     CodecBuffer *inputInfo = instance->bufferManagerWrapper->GetUsedInputDataBuffer(
161         instance->bufferManagerWrapper, QUEUE_TIME_OUT);
162     if (inputInfo == NULL) {
163         return HDF_ERR_TIMEOUT;
164     }
165 
166     inputInfoSendToClient->bufferCnt = inputInfo->bufferCnt;
167     inputInfoSendToClient->buffer[0].type = inputInfo->buffer[0].type;
168     if (!CopyCodecBufferWithTypeSwitch(instance, inputInfoSendToClient, inputInfo, false)) {
169         HDF_LOGE("%{public}s: copy CodecBuffer failed!", __func__);
170         return HDF_FAILURE;
171     }
172     // fd has been transmitted at the initial time, here set invalid to avoid being transmitted again
173     if (inputInfoSendToClient->buffer[0].type == BUFFER_TYPE_FD) {
174         inputInfoSendToClient->buffer[0].buf = NO_TRANSMIT_FD;
175     } else if (inputInfoSendToClient->buffer[0].type == BUFFER_TYPE_HANDLE) {
176         inputInfoSendToClient->buffer[0].buf = NO_TRANSMIT_BUFFERHANDLE;
177     }
178     return HDF_SUCCESS;
179 }
180 
GetFilledOutputInfo(struct CodecInstance * instance,CodecBuffer * outputInfoSendToClient)181 static int32_t GetFilledOutputInfo(struct CodecInstance *instance, CodecBuffer *outputInfoSendToClient)
182 {
183     if (instance == NULL || instance->bufferManagerWrapper == NULL || outputInfoSendToClient == NULL) {
184         HDF_LOGE("%{public}s failed: invalid parameter!", __func__);
185         return HDF_FAILURE;
186     }
187 
188     CodecBuffer *outputInfo = instance->bufferManagerWrapper->GetOutputDataBuffer(
189         instance->bufferManagerWrapper, QUEUE_TIME_OUT);
190     if (outputInfo == NULL) {
191         return HDF_ERR_TIMEOUT;
192     }
193 
194     outputInfoSendToClient->bufferCnt = outputInfo->bufferCnt;
195     outputInfoSendToClient->buffer[0].type = outputInfo->buffer[0].type;
196     if (!CopyCodecBufferWithTypeSwitch(instance, outputInfoSendToClient, outputInfo, false)) {
197         HDF_LOGE("%{public}s: copy CodecBuffer failed!", __func__);
198         return HDF_FAILURE;
199     }
200     // fd has been transmitted at the initial time, here set invalid to avoid being transmitted again
201     if (outputInfoSendToClient->buffer[0].type == BUFFER_TYPE_FD) {
202         outputInfoSendToClient->buffer[0].buf = NO_TRANSMIT_FD;
203     } else if (outputInfoSendToClient->buffer[0].type == BUFFER_TYPE_HANDLE) {
204         outputInfoSendToClient->buffer[0].buf = NO_TRANSMIT_BUFFERHANDLE;
205     }
206     return HDF_SUCCESS;
207 }
208 
CallbackTaskLoop(struct CodecInstance * instance,CodecBuffer * inputInfoSendToClient,CodecBuffer * outputInfoSendToClient)209 static void CallbackTaskLoop(struct CodecInstance *instance, CodecBuffer *inputInfoSendToClient,
210     CodecBuffer *outputInfoSendToClient)
211 {
212     int32_t acquireFd = 1;
213     bool codecTaskFinished = false;
214     int32_t getResult;
215     if (instance == NULL || inputInfoSendToClient == NULL || outputInfoSendToClient == NULL) {
216         HDF_LOGE("%{public}s failed: invalid parameter!", __func__);
217         return;
218     }
219     while (instance->codecCallbackStatus == CODEC_STATUS_STARTED) {
220         if (instance->codecStatus != CODEC_STATUS_STARTED) {
221             codecTaskFinished = true;
222         }
223         if (!instance->inputEos && GetUsedInputInfo(instance, inputInfoSendToClient) == HDF_SUCCESS) {
224 #ifndef CODEC_HAL_PASSTHROUGH
225             instance->callbackProxy->InputBufferAvailable(instance->callbackProxy, instance->callbackUserData,
226                 inputInfoSendToClient, &acquireFd);
227 #else
228             instance->codecCallback->InputBufferAvailable(instance->callbackUserData,
229                 inputInfoSendToClient, &acquireFd);
230 #endif
231         }
232         getResult = GetFilledOutputInfo(instance, outputInfoSendToClient);
233         if (getResult == HDF_SUCCESS) {
234 #ifndef CODEC_HAL_PASSTHROUGH
235             instance->callbackProxy->OutputBufferAvailable(instance->callbackProxy, instance->callbackUserData,
236                 outputInfoSendToClient, &acquireFd);
237 #else
238             instance->codecCallback->OutputBufferAvailable(instance->callbackUserData,
239                 outputInfoSendToClient, &acquireFd);
240 #endif
241         } else if (getResult == HDF_ERR_TIMEOUT && codecTaskFinished) {
242             HDF_LOGI("%{public}s: no output any more!", __func__);
243             EmptyCodecBuffer(outputInfoSendToClient);
244             outputInfoSendToClient->flag = STREAM_FLAG_EOS;
245 #ifndef CODEC_HAL_PASSTHROUGH
246             instance->callbackProxy->OutputBufferAvailable(instance->callbackProxy, instance->callbackUserData,
247                 outputInfoSendToClient, &acquireFd);
248 #else
249             instance->codecCallback->OutputBufferAvailable(instance->callbackUserData,
250                 outputInfoSendToClient, &acquireFd);
251 #endif
252             break;
253         }
254         if (outputInfoSendToClient->flag & STREAM_FLAG_EOS) {
255             HDF_LOGI("%{public}s: output reach STREAM_FLAG_EOS!", __func__);
256             break;
257         }
258     }
259 }
260 
CodecCallbackTaskThread(void * arg)261 static void *CodecCallbackTaskThread(void *arg)
262 {
263     HDF_LOGI("%{public}s: codec callback task thread started!", __func__);
264     if (arg == NULL) {
265         HDF_LOGE("%{public}s: Invalid arg, exit CodecTaskThread!", __func__);
266         return NULL;
267     }
268     struct CodecInstance *instance = (struct CodecInstance *)arg;
269 
270     CodecBuffer *inputInfoSendToClient = NULL;
271     CodecBuffer *outputInfoSendToClient = NULL;
272     if (!InitData(&inputInfoSendToClient, &outputInfoSendToClient)) {
273         HDF_LOGE("%{public}s: InitData failed!", __func__);
274         return NULL;
275     }
276 
277     CallbackTaskLoop(instance, inputInfoSendToClient, outputInfoSendToClient);
278 
279     OsalMutexLock(&instance->codecCallbackStatusLock);
280     instance->codecCallbackStatus = CODEC_STATUS_STOPPED;
281     pthread_cond_signal(&instance->codecCallbackStatusCond);
282     OsalMutexUnlock(&instance->codecCallbackStatusLock);
283 
284     OsalMemFree(inputInfoSendToClient);
285     OsalMemFree(outputInfoSendToClient);
286     HDF_LOGI("%{public}s: codec callback task thread finished!", __func__);
287     return NULL;
288 }
289 
GetCodecInstance(void)290 struct CodecInstance* GetCodecInstance(void)
291 {
292     struct CodecInstance *instance = (struct CodecInstance *)OsalMemCalloc(sizeof(struct CodecInstance));
293     if (instance == NULL) {
294         HDF_LOGE("%{public}s: instance mem alloc failed", __func__);
295         return NULL;
296     }
297 
298     instance->codecStatus = CODEC_STATUS_IDLE;
299     instance->codecCallbackStatus = CODEC_STATUS_IDLE;
300     instance->inputEos = false;
301     instance->hasCustomerCallback = false;
302     return instance;
303 }
304 
InitCodecInstance(struct CodecInstance * instance,struct CodecOemIf * oemIf)305 int32_t InitCodecInstance(struct CodecInstance *instance, struct CodecOemIf *oemIf)
306 {
307     if (instance == NULL || oemIf == NULL) {
308         HDF_LOGE("%{public}s: Invalid param!", __func__);
309         return HDF_FAILURE;
310     }
311     instance->codecOemIface = oemIf;
312     instance->bufferManagerWrapper = GetBufferManager();
313     if (instance->bufferManagerWrapper == NULL) {
314         HDF_LOGE("%{public}s: GetBufferManager failed", __func__);
315         return HDF_FAILURE;
316     }
317 
318     int32_t ret = OsalMutexInit(&instance->codecStatusLock);
319     if (ret != HDF_SUCCESS) {
320         HDF_LOGE("%{public}s: OsalMutexInit failed, ret:%{public}d", __func__, ret);
321         return HDF_FAILURE;
322     }
323     ret = pthread_cond_init(&instance->codecStatusCond, NULL);
324     if (ret != 0) {
325         HDF_LOGE("%{public}s: pthread_cond_init failed, ret:%{public}d", __func__, ret);
326         return HDF_FAILURE;
327     }
328     ret = OsalMutexInit(&instance->codecCallbackStatusLock);
329     if (ret != HDF_SUCCESS) {
330         HDF_LOGE("%{public}s: OsalMutexInit failed, ret:%{public}d", __func__, ret);
331         return HDF_FAILURE;
332     }
333     ret = pthread_cond_init(&instance->codecCallbackStatusCond, NULL);
334     if (ret != 0) {
335         HDF_LOGE("%{public}s: pthread_cond_init failed, ret:%{public}d", __func__, ret);
336         return HDF_FAILURE;
337     }
338 
339     return HDF_SUCCESS;
340 }
341 
RunCodecInstance(struct CodecInstance * instance)342 int32_t RunCodecInstance(struct CodecInstance *instance)
343 {
344     if (instance == NULL) {
345         HDF_LOGE("%{public}s: Invalid param!", __func__);
346         return HDF_FAILURE;
347     }
348 
349     instance->codecStatus = CODEC_STATUS_STARTED;
350     pthread_attr_init(&instance->codecTaskAttr);
351     pthread_attr_setdetachstate(&instance->codecTaskAttr, PTHREAD_CREATE_JOINABLE);
352     int32_t ret = pthread_create(&instance->codecTask, NULL, CodecTaskThread, instance);
353     if (ret != 0) {
354         HDF_LOGE("%{public}s: run codec task thread failed!", __func__);
355         instance->codecStatus = CODEC_STATUS_STOPPED;
356         return HDF_FAILURE;
357     }
358 
359     if (instance->hasCustomerCallback) {
360         instance->codecCallbackStatus = CODEC_STATUS_STARTED;
361         pthread_attr_init(&instance->codecCallbackTaskAttr);
362         pthread_attr_setdetachstate(&instance->codecCallbackTaskAttr, PTHREAD_CREATE_JOINABLE);
363         ret = pthread_create(&instance->codecCallbackTask, NULL, CodecCallbackTaskThread, instance);
364         if (ret != 0) {
365             HDF_LOGE("%{public}s: run codec callback task thread failed!", __func__);
366             instance->codecStatus = CODEC_STATUS_STOPPING;
367             instance->codecCallbackStatus = CODEC_STATUS_STOPPED;
368             return HDF_FAILURE;
369         }
370     }
371     return HDF_SUCCESS;
372 }
373 
StopCodecInstance(struct CodecInstance * instance)374 int32_t StopCodecInstance(struct CodecInstance *instance)
375 {
376     if (instance == NULL) {
377         HDF_LOGE("%{public}s: Invalid param!", __func__);
378         return HDF_FAILURE;
379     }
380 
381     OsalMutexLock(&instance->codecStatusLock);
382     if (instance->codecStatus == CODEC_STATUS_STARTED) {
383         instance->codecStatus = CODEC_STATUS_STOPPING;
384     } else {
385         instance->codecStatus = CODEC_STATUS_STOPPED;
386     }
387     OsalMutexUnlock(&instance->codecStatusLock);
388 
389     OsalMutexLock(&instance->codecCallbackStatusLock);
390     if (instance->codecCallbackStatus == CODEC_STATUS_STARTED) {
391         instance->codecCallbackStatus = CODEC_STATUS_STOPPING;
392     } else {
393         instance->codecCallbackStatus = CODEC_STATUS_STOPPED;
394     }
395     OsalMutexUnlock(&instance->codecCallbackStatusLock);
396 
397     return HDF_SUCCESS;
398 }
399 
DestroyCodecInstance(struct CodecInstance * instance)400 int32_t DestroyCodecInstance(struct CodecInstance *instance)
401 {
402     if (instance == NULL) {
403         HDF_LOGE("%{public}s: Invalid param!", __func__);
404         return HDF_FAILURE;
405     }
406 
407     OsalMutexLock(&instance->codecStatusLock);
408     if (instance->codecStatus == CODEC_STATUS_STARTED ||
409         instance->codecStatus == CODEC_STATUS_STOPPING) {
410         HDF_LOGI("%{public}s: wait codec task stop!", __func__);
411         if (instance->codecStatusLock.realMutex != NULL) {
412             pthread_cond_wait(&instance->codecStatusCond,
413                 (pthread_mutex_t *)instance->codecStatusLock.realMutex);
414         }
415     }
416     OsalMutexUnlock(&instance->codecStatusLock);
417     pthread_cond_destroy(&instance->codecStatusCond);
418     OsalMutexDestroy(&instance->codecStatusLock);
419     pthread_attr_destroy(&instance->codecTaskAttr);
420 
421     OsalMutexLock(&instance->codecCallbackStatusLock);
422     if (instance->codecCallbackStatus == CODEC_STATUS_STARTED ||
423         instance->codecCallbackStatus == CODEC_STATUS_STOPPING) {
424         HDF_LOGI("%{public}s: wait codec callback task stop!", __func__);
425         if (instance->codecStatusLock.realMutex != NULL) {
426             pthread_cond_wait(&instance->codecCallbackStatusCond,
427                 (pthread_mutex_t *)instance->codecCallbackStatusLock.realMutex);
428         }
429     }
430     OsalMutexUnlock(&instance->codecCallbackStatusLock);
431     pthread_cond_destroy(&instance->codecCallbackStatusCond);
432     OsalMutexDestroy(&instance->codecCallbackStatusLock);
433     pthread_attr_destroy(&instance->codecCallbackTaskAttr);
434 
435     ReleaseInputShm(instance);
436     ReleaseOutputShm(instance);
437     ReleaseInputInfo(instance);
438     ReleaseOutputInfo(instance);
439 
440     DeleteBufferManager(&(instance->bufferManagerWrapper));
441     return HDF_SUCCESS;
442 }
443 
SetOemCodecBufferType(CodecBuffer * bufferToOemCodec,CodecBuffer * bufferInQueue)444 bool SetOemCodecBufferType(CodecBuffer *bufferToOemCodec, CodecBuffer *bufferInQueue)
445 {
446     if (bufferToOemCodec == NULL || bufferInQueue == NULL) {
447         HDF_LOGE("%{public}s: Invalid params!", __func__);
448         return false;
449     }
450     if (bufferInQueue->buffer[0].type == BUFFER_TYPE_HANDLE) {
451         bufferToOemCodec->buffer[0].type = BUFFER_TYPE_HANDLE;
452     } else {
453         bufferToOemCodec->buffer[0].type = BUFFER_TYPE_VIRTUAL;
454     }
455     return true;
456 }
457 
AddInputShm(struct CodecInstance * instance,const CodecBufferInfo * bufferInfo,int32_t bufferId)458 int32_t AddInputShm(struct CodecInstance *instance, const CodecBufferInfo *bufferInfo, int32_t bufferId)
459 {
460     if (instance == NULL || bufferInfo == NULL) {
461         HDF_LOGE("%{public}s: Invalid param!", __func__);
462         return HDF_FAILURE;
463     }
464     int32_t count = instance->inputBuffersCount;
465     if (count >= MAX_BUFFER_NUM) {
466         HDF_LOGE("%{public}s: ShareMemory buffer array full!", __func__);
467         return HDF_FAILURE;
468     }
469     instance->inputBuffers[count].id = bufferId;
470     instance->inputBuffers[count].size = bufferInfo->capacity;
471     instance->inputBuffers[count].type = bufferInfo->type;
472     if (bufferInfo->type == BUFFER_TYPE_HANDLE) {
473         BufferHandle *bufferHandle = (BufferHandle *)bufferInfo->buf;
474         if (bufferHandle == NULL) {
475             HDF_LOGE("%{public}s: null bufferHandle!", __func__);
476             return HDF_FAILURE;
477         }
478         instance->inputBuffers[count].fd = bufferHandle->fd;
479     } else if (bufferInfo->type == BUFFER_TYPE_FD) {
480         instance->inputBuffers[count].fd = (int32_t)bufferInfo->buf;
481         if (OpenFdShareMemory(&instance->inputBuffers[count]) != HDF_SUCCESS) {
482             return HDF_FAILURE;
483         }
484     }
485     instance->inputBuffersCount++;
486     return HDF_SUCCESS;
487 }
488 
AddOutputShm(struct CodecInstance * instance,const CodecBufferInfo * bufferInfo,int32_t bufferId)489 int32_t AddOutputShm(struct CodecInstance *instance, const CodecBufferInfo *bufferInfo, int32_t bufferId)
490 {
491     if (instance == NULL || bufferInfo == NULL) {
492         HDF_LOGE("%{public}s: Invalid param!", __func__);
493         return HDF_FAILURE;
494     }
495     int32_t count = instance->outputBuffersCount;
496     if (count >= MAX_BUFFER_NUM) {
497         HDF_LOGE("%{public}s: ShareMemory buffer array full!", __func__);
498         return HDF_FAILURE;
499     }
500     instance->outputBuffers[count].id = bufferId;
501     instance->outputBuffers[count].size = bufferInfo->capacity;
502     instance->outputBuffers[count].type = bufferInfo->type;
503     if (bufferInfo->type == BUFFER_TYPE_HANDLE) {
504         BufferHandle *bufferHandle = (BufferHandle *)bufferInfo->buf;
505         if (bufferHandle == NULL) {
506             HDF_LOGE("%{public}s: null bufferHandle!", __func__);
507             return HDF_FAILURE;
508         }
509         instance->outputBuffers[count].fd = bufferHandle->fd;
510     } else if (bufferInfo->type == BUFFER_TYPE_FD) {
511         instance->outputBuffers[count].fd = (int32_t)bufferInfo->buf;
512         if (OpenFdShareMemory(&instance->outputBuffers[count]) != HDF_SUCCESS) {
513             return HDF_FAILURE;
514         }
515     }
516     instance->outputBuffersCount++;
517     return HDF_SUCCESS;
518 }
519 
GetShmById(struct CodecInstance * instance,int32_t id)520 static ShareMemory* GetShmById(struct CodecInstance *instance, int32_t id)
521 {
522     int32_t i;
523     if (instance == NULL) {
524         HDF_LOGE("%{public}s: Invalid param!", __func__);
525         return NULL;
526     }
527     for (i = 0; i < instance->inputBuffersCount; i++) {
528         if (instance->inputBuffers[i].id == id) {
529             return &(instance->inputBuffers[i]);
530         }
531     }
532     for (i = 0; i < instance->outputBuffersCount; i++) {
533         if (instance->outputBuffers[i].id == id) {
534             return &(instance->outputBuffers[i]);
535         }
536     }
537     HDF_LOGE("%{public}s: not found for bufferId:%{public}d!", __func__, id);
538     return NULL;
539 }
540 
GetFdById(struct CodecInstance * instance,int32_t id)541 int32_t GetFdById(struct CodecInstance *instance, int32_t id)
542 {
543     if (instance == NULL) {
544         HDF_LOGE("%{public}s: Invalid param!", __func__);
545         return HDF_FAILURE;
546     }
547     int32_t i;
548     for (i = 0; i < instance->inputBuffersCount; i++) {
549         if (instance->inputBuffers[i].id == id) {
550             return instance->inputBuffers[i].fd;
551         }
552     }
553     for (i = 0; i < instance->outputBuffersCount; i++) {
554         if (instance->outputBuffers[i].id == id) {
555             return instance->outputBuffers[i].fd;
556         }
557     }
558     HDF_LOGE("%{public}s: not found bufferId:%{public}d!", __func__, id);
559     return HDF_FAILURE;
560 }
561 
ReleaseInputShm(struct CodecInstance * instance)562 void ReleaseInputShm(struct CodecInstance *instance)
563 {
564     if (instance == NULL) {
565         HDF_LOGE("%{public}s: Invalid param!", __func__);
566         return;
567     }
568     for (int32_t i = 0; i < instance->inputBuffersCount; i++) {
569         if (instance->inputBuffers[i].type == BUFFER_TYPE_FD) {
570             ReleaseFdShareMemory(&instance->inputBuffers[i]);
571         }
572     }
573 }
ReleaseOutputShm(struct CodecInstance * instance)574 void ReleaseOutputShm(struct CodecInstance *instance)
575 {
576     if (instance == NULL) {
577         HDF_LOGE("%{public}s: Invalid param!", __func__);
578         return;
579     }
580     for (int32_t i = 0; i < instance->outputBuffersCount; i++) {
581         if (instance->outputBuffers[i].type == BUFFER_TYPE_FD) {
582             ReleaseFdShareMemory(&instance->outputBuffers[i]);
583         }
584     }
585 }
586 
AddInputInfo(struct CodecInstance * instance,CodecBuffer * info)587 int32_t AddInputInfo(struct CodecInstance *instance, CodecBuffer *info)
588 {
589     if (instance == NULL || info == NULL) {
590         HDF_LOGE("%{public}s: Invalid param!", __func__);
591         return HDF_FAILURE;
592     }
593     if (instance->inputInfoCount >= MAX_BUFFER_NUM) {
594         HDF_LOGE("%{public}s: CodecBuffer array full!", __func__);
595         return HDF_FAILURE;
596     }
597     instance->inputInfos[instance->inputInfoCount] = info;
598     instance->inputInfoCount++;
599     return HDF_SUCCESS;
600 }
601 
AddOutputInfo(struct CodecInstance * instance,CodecBuffer * info)602 int32_t AddOutputInfo(struct CodecInstance *instance, CodecBuffer *info)
603 {
604     if (instance == NULL || info == NULL) {
605         HDF_LOGE("%{public}s: Invalid param!", __func__);
606         return HDF_FAILURE;
607     }
608     if (instance->outputInfoCount >= MAX_BUFFER_NUM) {
609         HDF_LOGE("%{public}s: CodecBuffer array full!", __func__);
610         return HDF_FAILURE;
611     }
612     instance->outputInfos[instance->outputInfoCount] = info;
613     instance->outputInfoCount++;
614     return HDF_SUCCESS;
615 }
616 
GetInputInfo(struct CodecInstance * instance,uint32_t id)617 CodecBuffer* GetInputInfo(struct CodecInstance *instance, uint32_t id)
618 {
619     if (instance == NULL) {
620         HDF_LOGE("%{public}s: Invalid param!", __func__);
621         return NULL;
622     }
623     for (int32_t i = 0; i < instance->inputInfoCount; i++) {
624         if (instance->inputInfos[i]->bufferId == id) {
625             return instance->inputInfos[i];
626         }
627     }
628     HDF_LOGE("%{public}s: not found bufferId:%{public}d!", __func__, id);
629     return NULL;
630 }
631 
GetOutputInfo(struct CodecInstance * instance,uint32_t id)632 CodecBuffer* GetOutputInfo(struct CodecInstance *instance, uint32_t id)
633 {
634     if (instance == NULL) {
635         HDF_LOGE("%{public}s: Invalid param!", __func__);
636         return NULL;
637     }
638     for (int32_t i = 0; i < instance->outputInfoCount; i++) {
639         if (instance->outputInfos[i]->bufferId == id) {
640             return instance->outputInfos[i];
641         }
642     }
643     HDF_LOGE("%{public}s: not found bufferId:%{public}d!", __func__, id);
644     return NULL;
645 }
646 
ReleaseCodecBuffer(CodecBuffer * info)647 void ReleaseCodecBuffer(CodecBuffer *info)
648 {
649     if (info == NULL) {
650         HDF_LOGI("%{public}s: Invalid param!", __func__);
651         return;
652     }
653     for (uint32_t i = 0; i < info->bufferCnt; i++) {
654         if (info->buffer[i].type == BUFFER_TYPE_HANDLE) {
655             FreeBufferHandle((BufferHandle *)info->buffer[i].buf);
656         }
657     }
658     OsalMemFree(info);
659 }
660 
ReleaseInputInfo(struct CodecInstance * instance)661 void ReleaseInputInfo(struct CodecInstance *instance)
662 {
663     if (instance == NULL) {
664         HDF_LOGE("%{public}s: Invalid param!", __func__);
665         return;
666     }
667     for (int32_t i = 0; i < instance->inputInfoCount; i++) {
668         ReleaseCodecBuffer(instance->inputInfos[i]);
669         instance->inputInfos[i] = NULL;
670     }
671 }
672 
ReleaseOutputInfo(struct CodecInstance * instance)673 void ReleaseOutputInfo(struct CodecInstance *instance)
674 {
675     if (instance == NULL) {
676         HDF_LOGE("%{public}s: Invalid param!", __func__);
677         return;
678     }
679     for (int32_t i = 0; i < instance->outputInfoCount; i++) {
680         ReleaseCodecBuffer(instance->outputInfos[i]);
681         instance->outputInfos[i] = NULL;
682     }
683 }
684 
ResetBuffers(struct CodecInstance * instance)685 void ResetBuffers(struct CodecInstance *instance)
686 {
687     if (instance == NULL) {
688         HDF_LOGE("%{public}s: Invalid param!", __func__);
689         return;
690     }
691     int32_t i;
692     ReleaseInputShm(instance);
693     ReleaseOutputShm(instance);
694     for (i = 0; i< instance->inputInfoCount; i++) {
695         ReleaseCodecBuffer(instance->inputInfos[i]);
696     }
697     for (i = 0; i< instance->outputInfoCount; i++) {
698         ReleaseCodecBuffer(instance->outputInfos[i]);
699     }
700 
701     instance->inputBuffersCount = 0;
702     instance->outputBuffersCount = 0;
703     instance->inputInfoCount = 0;
704     instance->outputInfoCount = 0;
705 }
706 
EmptyCodecBuffer(CodecBuffer * buf)707 void EmptyCodecBuffer(CodecBuffer *buf)
708 {
709     if (buf == NULL) {
710         return;
711     }
712     for (uint32_t i = 0; i < buf->bufferCnt; i++) {
713         buf->buffer[i].length = 0;
714         buf->buffer[i].offset = 0;
715     }
716 }
717 
CopyCodecBufferWithTypeSwitch(struct CodecInstance * instance,CodecBuffer * dst,const CodecBuffer * src,bool ignoreBuf)718 bool CopyCodecBufferWithTypeSwitch(struct CodecInstance *instance, CodecBuffer *dst,
719     const CodecBuffer *src, bool ignoreBuf)
720 {
721     if (dst == NULL || src == NULL) {
722         HDF_LOGE("%{public}s: dst or src is Nullpoint", __func__);
723         return false;
724     }
725     if (dst->bufferCnt != src->bufferCnt) {
726         HDF_LOGE("%{public}s: size not match", __func__);
727         return false;
728     }
729     dst->bufferId = src->bufferId;
730     dst->timeStamp = src->timeStamp;
731     dst->flag = src->flag;
732     for (uint32_t i = 0; i < src->bufferCnt; i++) {
733         dst->buffer[i].offset = src->buffer[i].offset;
734         dst->buffer[i].length = src->buffer[i].length;
735         dst->buffer[i].capacity = src->buffer[i].capacity;
736         if (ignoreBuf) {
737             continue;
738         } else if (dst->buffer[i].type == src->buffer[i].type) {
739             dst->buffer[i].buf = src->buffer[i].buf;
740         } else if (dst->buffer[i].type == BUFFER_TYPE_VIRTUAL && src->buffer[i].type == BUFFER_TYPE_FD) {
741             dst->buffer[i].buf = (intptr_t)GetShmById(instance, src->bufferId)->virAddr;
742         } else if (dst->buffer[i].type == BUFFER_TYPE_VIRTUAL && src->buffer[i].type == BUFFER_TYPE_HANDLE) {
743             dst->buffer[i].buf = (intptr_t)GetShmById(instance, src->bufferId)->virAddr;
744         }
745         if (dst->buffer[i].buf == 0) {
746             HDF_LOGE("%{public}s: buf value invalid! bufferId:%{public}d", __func__, src->bufferId);
747             return false;
748         }
749     }
750     return true;
751 }
752 
DupBufferHandle(const BufferHandle * handle)753 static BufferHandle *DupBufferHandle(const BufferHandle *handle)
754 {
755     if (handle == NULL) {
756         HDF_LOGE("%{public}s buffer handle is NULL", __func__);
757         return NULL;
758     }
759 
760     BufferHandle *newHandle = AllocateBufferHandle(handle->reserveFds, handle->reserveInts);
761     if (newHandle == NULL) {
762         HDF_LOGE("%{public}s AllocateBufferHandle failed, newHandle is NULL", __func__);
763         return NULL;
764     }
765 
766     newHandle->fd = handle->fd;
767     newHandle->width = handle->width;
768     newHandle->stride = handle->stride;
769     newHandle->height = handle->height;
770     newHandle->size = handle->size;
771     newHandle->format = handle->format;
772     newHandle->usage = handle->usage;
773     newHandle->virAddr = handle->virAddr;
774     newHandle->phyAddr = handle->phyAddr;
775 
776     return newHandle;
777 }
778 
DupCodecBuffer(const CodecBuffer * src)779 CodecBuffer* DupCodecBuffer(const CodecBuffer *src)
780 {
781     if (src == NULL) {
782         HDF_LOGE("%{public}s: CodecBuffer src Nullpoint", __func__);
783         return NULL;
784     }
785     int32_t size = sizeof(CodecBuffer) + sizeof(CodecBufferInfo) * src->bufferCnt;
786     CodecBuffer *dst = (CodecBuffer *)OsalMemAlloc(size);
787     if (dst == NULL) {
788         HDF_LOGE("%{public}s: malloc dst failed", __func__);
789         return NULL;
790     }
791     int32_t ret = memcpy_s(dst, size, src, size);
792     if (ret != EOK) {
793         HDF_LOGE("%{public}s: memcpy_s failed, error code: %{public}d", __func__, ret);
794         OsalMemFree(dst);
795         return NULL;
796     }
797     for (uint32_t i = 0; i < src->bufferCnt; i++) {
798         if (dst->buffer[i].type == BUFFER_TYPE_HANDLE) {
799             dst->buffer[i].buf = (intptr_t)DupBufferHandle((BufferHandle *)src->buffer[i].buf);
800         }
801     }
802     return dst;
803 }
804 
805