blob: 37dbadea23fedc56a9b3fcf5c4729236a1bf1258 [file] [log] [blame]
b.liuf191eb72024-12-12 10:45:23 +08001/*
2* mbtk_loop_buffer.c
3*
4* MBTK loop buffer sources.
5*
6*/
7/******************************************************************************
8
9 EDIT HISTORY FOR FILE
10
11 WHEN WHO WHAT,WHERE,WHY
12-------- -------- -------------------------------------------------------
132024/12/5 LiuBin Initial version
14
15******************************************************************************/
16#include <stdio.h>
17#include <string.h>
18#include <stdlib.h>
19#include <unistd.h>
20#include <errno.h>
21#include <pthread.h>
22
23#include "mbtk_str.h"
24#include "mbtk_utils.h"
25#include "mbtk_log.h"
26#include "mbtk_type.h"
27#include "mbtk_loop_buffer.h"
28
29typedef struct {
30 int size;
31 uint8 *buffer;
32
33 int head;
34 int tail;
35
36 int avail_size;
37
38 pthread_mutex_t mutex;
39} loop_buffer_t;
40
41mbtk_loop_buff_handle* mbtk_loopbuff_get(int size)
42{
43 if(size <= 0) {
44 LOGE("size error : %d", size);
45 return NULL;
46 }
47
48 loop_buffer_t *buff = (loop_buffer_t*)malloc(sizeof(loop_buffer_t));
49 if(buff == NULL) {
50 LOGE("malloc() fail:%d", errno);
51 return NULL;
52 }
53
54 memset(buff, 0, sizeof(loop_buffer_t));
55 buff->buffer = (uint8*)malloc(size);
56 if(buff == NULL) {
57 free(buff);
58 LOGE("malloc() fail:%d", errno);
59 return NULL;
60 }
61 buff->size = buff->avail_size = size;
62
63 pthread_mutex_init(&buff->mutex, NULL);
64
65 return buff;
66}
67
68int mbtk_loopbuff_free(mbtk_loop_buff_handle* handle)
69{
70 if(handle == NULL) {
71 LOGE("handle is NULL");
72 return -1;
73 }
74
75 loop_buffer_t *buff = (loop_buffer_t*)handle;
76 if(buff->buffer) {
77 free(buff->buffer);
78 }
79 pthread_mutex_destroy(&buff->mutex);
80 free(buff);
81
82 return 0;
83}
84
85int mbtk_loopbuff_write(mbtk_loop_buff_handle* handle, const void *data, int data_len)
86{
87 if(handle == NULL || data == NULL || data_len <= 0) {
88 LOGE("ARG error.");
89 return -1;
90 }
91
92 loop_buffer_t *loop_buff = (loop_buffer_t*)handle;
93 pthread_mutex_lock(&loop_buff->mutex);
94 if(loop_buff->avail_size == 0) {
95 LOGV("Buffer full.");
96 pthread_mutex_unlock(&loop_buff->mutex);
97 return -1;
98 } else {
99 int size = loop_buff->avail_size >= data_len ? data_len : loop_buff->avail_size;
100 // h t
101 // [...xxxxxxx...]
102 if(loop_buff->tail >= loop_buff->head) {
103 // h t t
104 // [...xxxxxxxyyy.]
105 if(loop_buff->tail + size <= loop_buff->size) {
106 memcpy(loop_buff->buffer + loop_buff->tail, data, size);
107 loop_buff->tail += size;
108 loop_buff->tail %= loop_buff->size;
109 } else {
110 // t h t
111 // [yyy...xxxxyy]
112 int len_right = loop_buff->size - loop_buff->tail; // len_right < size
113 memcpy(loop_buff->buffer + loop_buff->tail, data, len_right);
114 loop_buff->tail = 0;
115 memcpy(loop_buff->buffer + loop_buff->tail, data + len_right, size - len_right);
116 loop_buff->tail += (size - len_right);
117 }
118 } else {
119 // t t h
120 // [xxxyyy...xxxxx]
121 memcpy(loop_buff->buffer + loop_buff->tail, data, size);
122 loop_buff->tail += size;
123 loop_buff->tail %= loop_buff->size;
124 }
125 loop_buff->avail_size -= size;
126 pthread_mutex_unlock(&loop_buff->mutex);
127 return size;
128 }
129}
130
131int mbtk_loopbuff_writen(mbtk_loop_buff_handle* handle, const void *data, int data_len)
132{
133 int len_count = 0;
134 // LOGD("mbtk_loopbuff_write() start.");
135 while(len_count < data_len) {
136 int len = mbtk_loopbuff_write(handle, data + len_count, data_len - len_count);
137 if(len > 0) {
138#if 0
139 if(len != data_len - len_count) {
140 LOGD("%d/%d", len, data_len - len_count);
141 }
142#endif
143 len_count += len;
144 } else {
145 usleep(5000);
146 }
147 }
148#if 0
149 if(data_len != len_count) {
150 LOGD("mbtk_loopbuff_write() xxxxxxxxxxxxxxx fail : %d/%d", len_count, data_len);
151 }
152#endif
153 return len_count;
154}
155
156int mbtk_loopbuff_read(mbtk_loop_buff_handle* handle, void *data, int data_len)
157{
158 if(handle == NULL || data == NULL || data_len <= 0) {
159 LOGE("ARG error.");
160 return -1;
161 }
162
163 loop_buffer_t *loop_buff = (loop_buffer_t*)handle;
164 pthread_mutex_lock(&loop_buff->mutex);
165 if(loop_buff->avail_size == loop_buff->size) { // Buffer is empty.
166 pthread_mutex_unlock(&loop_buff->mutex);
167 LOGV("Buffer is empty.");
168 return 0;
169 } else {
170 int size = (loop_buff->size - loop_buff->avail_size) >= data_len ? data_len :
171 (loop_buff->size - loop_buff->avail_size);
172 // h h t
173 // [...yyyxxxx...]
174 if(loop_buff->tail > loop_buff->head) {
175 memcpy(data, loop_buff->buffer + loop_buff->head, size);
176 loop_buff->head += size;
177 } else {
178 // t h h
179 // [xxxxx.....yyyxx]
180 if(loop_buff->head + size <= loop_buff->size) {// [xxt...hxxxxxx]
181 memcpy(data, loop_buff->buffer + loop_buff->head, size);
182 loop_buff->head += size;
183 loop_buff->head %= loop_buff->size;
184 } else {
185 // h t h
186 // [yyyxxxx.....yyy]
187 int len_right = loop_buff->size - loop_buff->head; // len_right < size
188 memcpy(data, loop_buff->buffer + loop_buff->head, len_right);
189 loop_buff->head = 0;
190 memcpy(data + len_right, loop_buff->buffer + loop_buff->head, size - len_right);
191 loop_buff->head += (size - len_right);
192 }
193 }
194 loop_buff->avail_size += size;
195 pthread_mutex_unlock(&loop_buff->mutex);
196 return size;
197 }
198}
199
200int mbtk_loopbuff_readn(mbtk_loop_buff_handle* handle, void *data, int data_len)
201{
202 int len_count = 0;
203 int read_count = 0;
204 while(len_count < data_len) {
205 int len = mbtk_loopbuff_read(handle, data + len_count, data_len - len_count);
206 if(len > 0) {
207 len_count += len;
208 } else {
209 usleep(5000);
210 }
211 read_count++;
212
213 if(read_count >= 20)
214 break;
215 }
216 return len_count;
217}
218
219
220// Only for read seek.
221int mbtk_loopbuff_seek(mbtk_loop_buff_handle* handle, int offset)
222{
223 if(handle == NULL) {
224 LOGE("ARG error.");
225 return -1;
226 }
227
228 if(offset == 0)
229 return 0;
230
231 loop_buffer_t *loop_buff = (loop_buffer_t*)handle;
232 pthread_mutex_lock(&loop_buff->mutex);
233 if(/*loop_buff->avail_size == loop_buff->size || */
234 offset > loop_buff->size || offset < -loop_buff->size) {
235 pthread_mutex_unlock(&loop_buff->mutex);
236 return -1;
237 } else {
238 if(offset > 0) {
239 int change = offset > (loop_buff->size - loop_buff->avail_size) ?
240 (loop_buff->size - loop_buff->avail_size) : offset;
241 loop_buff->head += change;
242 loop_buff->head %= loop_buff->size;
243 } else {
244 int change = -offset > loop_buff->avail_size ? loop_buff->avail_size : -offset;
245 loop_buff->head -= change;
246 if(loop_buff->head < 0)
247 loop_buff->head = loop_buff->size + loop_buff->head;
248 }
249
250 loop_buff->avail_size += offset;
251 pthread_mutex_unlock(&loop_buff->mutex);
252 return 0;
253 }
254}
255
256int mbtk_loopbuff_size(mbtk_loop_buff_handle* handle)
257{
258 if(handle == NULL) {
259 LOGE("ARG error.");
260 return -1;
261 }
262
263 loop_buffer_t *loop_buff = (loop_buffer_t*)handle;
264 int size = 0;
265 pthread_mutex_lock(&loop_buff->mutex);
266 size = loop_buff->size - loop_buff->avail_size;
267 pthread_mutex_unlock(&loop_buff->mutex);
268 return size;
269}
270
271void mbtk_loopbuff_print(mbtk_loop_buff_handle* handle)
272{
273 if(handle == NULL) {
274 LOGE("ARG error.");
275 return;
276 }
277
278 loop_buffer_t *loop_buff = (loop_buffer_t*)handle;
279 pthread_mutex_lock(&loop_buff->mutex);
280 int data_size = loop_buff->size - loop_buff->avail_size;
281 if(data_size <= 0) {
282 LOGD("Buffer is NULL.");
283 } else {
284 uint8 *buff = (uint8*)malloc(data_size);
285 if(buff) {
286 // h t
287 // [...xxxxxxx...]
288 if(loop_buff->tail > loop_buff->head) {
289 memcpy(buff, loop_buff->buffer + loop_buff->head, data_size);
290 } else {
291 // t h
292 // [xxxxx.....xxxxx]
293 int len_right = loop_buff->size - loop_buff->head; // len_right < size
294 memcpy(buff, loop_buff->buffer + loop_buff->head, len_right);
295 if(data_size - len_right > 0) {
296 memcpy(buff + len_right, loop_buff->buffer, data_size - len_right);
297 }
298 }
299
300 LOGD("Head = %d, Tail = %d, Lenght = %d / %d", loop_buff->head, loop_buff->tail,
301 data_size, loop_buff->size);
302 log_hex("DATA", buff, data_size);
303 free(buff);
304 buff = NULL;
305 }
306 }
307 pthread_mutex_unlock(&loop_buff->mutex);
308}
309