b.liu | f191eb7 | 2024-12-12 10:45:23 +0800 | [diff] [blame] | 1 | /* |
| 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 | -------- -------- ------------------------------------------------------- |
| 13 | 2024/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 | |
| 29 | typedef 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 | |
| 41 | mbtk_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 | |
| 68 | int 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 | |
| 85 | int 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 | |
| 131 | int 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 | |
| 156 | int 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 | |
| 200 | int 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. |
| 221 | int 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 | |
| 256 | int 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 | |
| 271 | void 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 | |