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 "buffer_manager.h"
17 #include <securec.h>
18
19 template <class T>
BufferManager()20 BufferManager<T>::BufferManager()
21 {
22 OsalMutexInit(&bufferQueueLock);
23 OsalMutexInit(&usedBufferQueueLock);
24 }
25
26 template <class T>
~BufferManager()27 BufferManager<T>::~BufferManager()
28 {
29 OsalMutexDestroy(&bufferQueueLock);
30 OsalMutexDestroy(&usedBufferQueueLock);
31 }
32
33 template <class T>
Stop()34 void BufferManager<T>::Stop()
35 {
36 status = CODEC_STATUS_STOPPED;
37 }
38
39 template <class T>
GetBuffer(uint32_t timeoutMs,bool isChecking)40 T* BufferManager<T>::GetBuffer(uint32_t timeoutMs, bool isChecking)
41 {
42 OsalMutexLock(&bufferQueueLock);
43 T *inputData = nullptr;
44 inputData = PollBufferQueue(isChecking);
45 if (inputData == nullptr) {
46 if (timeoutMs == HDF_WAIT_FOREVER) {
47 // release lock and wait here, and check again later when notified
48 pthread_cond_wait(&inputCond, (pthread_mutex_t *)bufferQueueLock.realMutex);
49 inputData = PollBufferQueue(isChecking);
50 } else if (timeoutMs > 0) {
51 struct timespec time = {0};
52 ConstructTimespec(&time, timeoutMs);
53 // release lock and wait here, and check again later when notified or timeout
54 pthread_cond_timedwait(&inputCond, (pthread_mutex_t *)bufferQueueLock.realMutex, &time);
55 inputData = PollBufferQueue(isChecking);
56 }
57 }
58 OsalMutexUnlock(&bufferQueueLock);
59
60 return inputData;
61 }
62
63 template <class T>
GetUsedBuffer(uint32_t timeoutMs,bool isChecking)64 T* BufferManager<T>::GetUsedBuffer(uint32_t timeoutMs, bool isChecking)
65 {
66 OsalMutexLock(&usedBufferQueueLock);
67 T *outputData = nullptr;
68 outputData = PollUsedBufferQueue(isChecking);
69 if (outputData == nullptr) {
70 if (timeoutMs == HDF_WAIT_FOREVER) {
71 // release lock and wait here, and check again later when notified
72 pthread_cond_wait(&outputCond, (pthread_mutex_t *)usedBufferQueueLock.realMutex);
73 outputData = PollUsedBufferQueue(isChecking);
74 } else if (timeoutMs > 0) {
75 struct timespec time = {0};
76 ConstructTimespec(&time, timeoutMs);
77 // release lock and wait here, and check again later when notified or timeout
78 pthread_cond_timedwait(&outputCond, (pthread_mutex_t *)usedBufferQueueLock.realMutex, &time);
79 outputData = PollUsedBufferQueue(isChecking);
80 }
81 }
82 OsalMutexUnlock(&usedBufferQueueLock);
83
84 return outputData;
85 }
86
87 template <class T>
ConstructTimespec(struct timespec * time,uint32_t timeoutMs)88 void BufferManager<T>::ConstructTimespec(struct timespec *time, uint32_t timeoutMs)
89 {
90 memset_s(time, sizeof(timespec), 0, sizeof(timespec));
91 clock_gettime(CLOCK_REALTIME, time);
92 time->tv_sec += static_cast<int32_t>(timeoutMs) / HDF_KILO_UNIT;
93 time->tv_nsec += (static_cast<int32_t>(timeoutMs) % HDF_KILO_UNIT) * HDF_KILO_UNIT * HDF_KILO_UNIT;
94 if (time->tv_nsec >= HDF_NANO_UNITS) {
95 time->tv_nsec -= HDF_NANO_UNITS;
96 time->tv_sec += 1;
97 }
98 }
99
100 template <class T>
PollBufferQueue(bool isChecking)101 T* BufferManager<T>::PollBufferQueue(bool isChecking)
102 {
103 T *info = nullptr;
104 if (bufferQueue.size() == 0) {
105 return nullptr;
106 }
107 info = bufferQueue.front();
108 if (!isChecking) {
109 bufferQueue.pop();
110 }
111 return info;
112 }
113
114 template <class T>
PollUsedBufferQueue(bool isChecking)115 T* BufferManager<T>::PollUsedBufferQueue(bool isChecking)
116 {
117 T *info = nullptr;
118 if (usedBufferQueue.size() == 0) {
119 return nullptr;
120 }
121 info = usedBufferQueue.front();
122 if (!isChecking) {
123 usedBufferQueue.pop();
124 }
125 return info;
126 }
127
128 template <class T>
PutBuffer(T * info)129 void BufferManager<T>::PutBuffer(T *info)
130 {
131 OsalMutexLock(&bufferQueueLock);
132 bufferQueue.push(info);
133 pthread_cond_signal(&inputCond);
134 OsalMutexUnlock(&bufferQueueLock);
135 }
136
137 template <class T>
PutUsedBuffer(T * info)138 void BufferManager<T>::PutUsedBuffer(T *info)
139 {
140 OsalMutexLock(&usedBufferQueueLock);
141 usedBufferQueue.push(info);
142 pthread_cond_signal(&outputCond);
143 OsalMutexUnlock(&usedBufferQueueLock);
144 }
145
146 template class BufferManager<CodecBuffer>;
147