Add mbtk_loopbuff and rtp support.

Change-Id: Idc80af4efb8ff76c4afc59fdf1d3896b453e6ff4
diff --git a/mbtk/libmbtk_lib/common/mbtk_loopbuff.c b/mbtk/libmbtk_lib/common/mbtk_loopbuff.c
new file mode 100755
index 0000000..37dbade
--- /dev/null
+++ b/mbtk/libmbtk_lib/common/mbtk_loopbuff.c
@@ -0,0 +1,309 @@
+/*
+*    mbtk_loop_buffer.c
+*
+*    MBTK loop buffer sources.
+*
+*/
+/******************************************************************************
+
+                          EDIT HISTORY FOR FILE
+
+  WHEN        WHO       WHAT,WHERE,WHY
+--------    --------    -------------------------------------------------------
+2024/12/5     LiuBin      Initial version
+
+******************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include "mbtk_str.h"
+#include "mbtk_utils.h"
+#include "mbtk_log.h"
+#include "mbtk_type.h"
+#include "mbtk_loop_buffer.h"
+
+typedef struct {
+    int size;
+    uint8 *buffer;
+
+    int head;
+    int tail;
+
+    int avail_size;
+
+    pthread_mutex_t mutex;
+} loop_buffer_t;
+
+mbtk_loop_buff_handle* mbtk_loopbuff_get(int size)
+{
+    if(size <= 0) {
+        LOGE("size error : %d", size);
+        return NULL;
+    }
+
+    loop_buffer_t *buff = (loop_buffer_t*)malloc(sizeof(loop_buffer_t));
+    if(buff == NULL) {
+        LOGE("malloc() fail:%d", errno);
+        return NULL;
+    }
+
+    memset(buff, 0, sizeof(loop_buffer_t));
+    buff->buffer = (uint8*)malloc(size);
+    if(buff == NULL) {
+        free(buff);
+        LOGE("malloc() fail:%d", errno);
+        return NULL;
+    }
+    buff->size = buff->avail_size = size;
+
+    pthread_mutex_init(&buff->mutex, NULL);
+
+    return buff;
+}
+
+int mbtk_loopbuff_free(mbtk_loop_buff_handle* handle)
+{
+    if(handle == NULL) {
+        LOGE("handle is NULL");
+        return -1;
+    }
+
+    loop_buffer_t *buff = (loop_buffer_t*)handle;
+    if(buff->buffer) {
+        free(buff->buffer);
+    }
+    pthread_mutex_destroy(&buff->mutex);
+    free(buff);
+
+    return 0;
+}
+
+int mbtk_loopbuff_write(mbtk_loop_buff_handle* handle, const void *data, int data_len)
+{
+    if(handle == NULL || data == NULL || data_len <= 0) {
+        LOGE("ARG error.");
+        return -1;
+    }
+
+    loop_buffer_t *loop_buff = (loop_buffer_t*)handle;
+    pthread_mutex_lock(&loop_buff->mutex);
+    if(loop_buff->avail_size == 0) {
+        LOGV("Buffer full.");
+        pthread_mutex_unlock(&loop_buff->mutex);
+        return -1;
+    } else {
+        int size = loop_buff->avail_size >= data_len ? data_len : loop_buff->avail_size;
+        //     h      t
+        // [...xxxxxxx...]
+        if(loop_buff->tail >= loop_buff->head) {
+            //     h      t  t
+            // [...xxxxxxxyyy.]
+            if(loop_buff->tail + size <= loop_buff->size) {
+                memcpy(loop_buff->buffer + loop_buff->tail, data, size);
+                loop_buff->tail += size;
+                loop_buff->tail %= loop_buff->size;
+            } else {
+                //     t  h   t
+                // [yyy...xxxxyy]
+                int len_right = loop_buff->size - loop_buff->tail; // len_right < size
+                memcpy(loop_buff->buffer + loop_buff->tail, data, len_right);
+                loop_buff->tail = 0;
+                memcpy(loop_buff->buffer + loop_buff->tail, data + len_right, size - len_right);
+                loop_buff->tail += (size - len_right);
+            }
+        } else {
+            //     t  t  h
+            // [xxxyyy...xxxxx]
+            memcpy(loop_buff->buffer + loop_buff->tail, data, size);
+            loop_buff->tail += size;
+            loop_buff->tail %= loop_buff->size;
+        }
+        loop_buff->avail_size -= size;
+        pthread_mutex_unlock(&loop_buff->mutex);
+        return size;
+    }
+}
+
+int mbtk_loopbuff_writen(mbtk_loop_buff_handle* handle, const void *data, int data_len)
+{
+    int len_count = 0;
+    // LOGD("mbtk_loopbuff_write() start.");
+    while(len_count < data_len) {
+        int len = mbtk_loopbuff_write(handle, data + len_count, data_len - len_count);
+        if(len > 0) {
+#if 0
+            if(len != data_len - len_count) {
+                LOGD("%d/%d", len, data_len - len_count);
+            }
+#endif
+            len_count += len;
+        } else {
+            usleep(5000);
+        }
+    }
+#if 0
+    if(data_len != len_count) {
+        LOGD("mbtk_loopbuff_write() xxxxxxxxxxxxxxx fail : %d/%d", len_count, data_len);
+    }
+#endif
+    return len_count;
+}
+
+int mbtk_loopbuff_read(mbtk_loop_buff_handle* handle, void *data, int data_len)
+{
+    if(handle == NULL || data == NULL || data_len <= 0) {
+        LOGE("ARG error.");
+        return -1;
+    }
+
+    loop_buffer_t *loop_buff = (loop_buffer_t*)handle;
+    pthread_mutex_lock(&loop_buff->mutex);
+    if(loop_buff->avail_size == loop_buff->size) { // Buffer is empty.
+        pthread_mutex_unlock(&loop_buff->mutex);
+        LOGV("Buffer is empty.");
+        return 0;
+    } else {
+        int size = (loop_buff->size - loop_buff->avail_size) >= data_len ? data_len :
+                    (loop_buff->size - loop_buff->avail_size);
+        //     h  h   t
+        // [...yyyxxxx...]
+        if(loop_buff->tail > loop_buff->head) {
+            memcpy(data, loop_buff->buffer + loop_buff->head, size);
+            loop_buff->head += size;
+        } else {
+            //       t    h  h
+            // [xxxxx.....yyyxx]
+            if(loop_buff->head + size <= loop_buff->size) {// [xxt...hxxxxxx]
+                memcpy(data, loop_buff->buffer + loop_buff->head, size);
+                loop_buff->head += size;
+                loop_buff->head %= loop_buff->size;
+            } else {
+                //     h   t    h
+                // [yyyxxxx.....yyy]
+                int len_right = loop_buff->size - loop_buff->head; // len_right < size
+                memcpy(data, loop_buff->buffer + loop_buff->head, len_right);
+                loop_buff->head = 0;
+                memcpy(data + len_right, loop_buff->buffer + loop_buff->head, size - len_right);
+                loop_buff->head += (size - len_right);
+            }
+        }
+        loop_buff->avail_size += size;
+        pthread_mutex_unlock(&loop_buff->mutex);
+        return size;
+    }
+}
+
+int mbtk_loopbuff_readn(mbtk_loop_buff_handle* handle, void *data, int data_len)
+{
+    int len_count = 0;
+    int read_count = 0;
+    while(len_count < data_len) {
+        int len = mbtk_loopbuff_read(handle, data + len_count, data_len - len_count);
+        if(len > 0) {
+            len_count += len;
+        } else {
+            usleep(5000);
+        }
+        read_count++;
+
+        if(read_count >= 20)
+            break;
+    }
+    return len_count;
+}
+
+
+// Only for read seek.
+int mbtk_loopbuff_seek(mbtk_loop_buff_handle* handle, int offset)
+{
+    if(handle == NULL) {
+        LOGE("ARG error.");
+        return -1;
+    }
+
+    if(offset == 0)
+        return 0;
+
+    loop_buffer_t *loop_buff = (loop_buffer_t*)handle;
+    pthread_mutex_lock(&loop_buff->mutex);
+    if(/*loop_buff->avail_size == loop_buff->size || */
+        offset > loop_buff->size || offset < -loop_buff->size) {
+        pthread_mutex_unlock(&loop_buff->mutex);
+        return -1;
+    } else {
+        if(offset > 0) {
+            int change = offset > (loop_buff->size - loop_buff->avail_size) ?
+                (loop_buff->size - loop_buff->avail_size) : offset;
+            loop_buff->head += change;
+            loop_buff->head %= loop_buff->size;
+        } else {
+            int change = -offset > loop_buff->avail_size ? loop_buff->avail_size : -offset;
+            loop_buff->head -= change;
+            if(loop_buff->head < 0)
+                loop_buff->head = loop_buff->size + loop_buff->head;
+        }
+
+        loop_buff->avail_size += offset;
+        pthread_mutex_unlock(&loop_buff->mutex);
+        return 0;
+    }
+}
+
+int mbtk_loopbuff_size(mbtk_loop_buff_handle* handle)
+{
+    if(handle == NULL) {
+        LOGE("ARG error.");
+        return -1;
+    }
+
+    loop_buffer_t *loop_buff = (loop_buffer_t*)handle;
+    int size = 0;
+    pthread_mutex_lock(&loop_buff->mutex);
+    size = loop_buff->size - loop_buff->avail_size;
+    pthread_mutex_unlock(&loop_buff->mutex);
+    return size;
+}
+
+void mbtk_loopbuff_print(mbtk_loop_buff_handle* handle)
+{
+    if(handle == NULL) {
+        LOGE("ARG error.");
+        return;
+    }
+
+    loop_buffer_t *loop_buff = (loop_buffer_t*)handle;
+    pthread_mutex_lock(&loop_buff->mutex);
+    int data_size = loop_buff->size - loop_buff->avail_size;
+    if(data_size <= 0) {
+        LOGD("Buffer is NULL.");
+    } else {
+        uint8 *buff = (uint8*)malloc(data_size);
+        if(buff) {
+            //     h      t
+            // [...xxxxxxx...]
+            if(loop_buff->tail > loop_buff->head) {
+                memcpy(buff, loop_buff->buffer + loop_buff->head, data_size);
+            } else {
+                //       t    h
+                // [xxxxx.....xxxxx]
+                int len_right = loop_buff->size - loop_buff->head; // len_right < size
+                memcpy(buff, loop_buff->buffer + loop_buff->head, len_right);
+                if(data_size - len_right > 0) {
+                    memcpy(buff + len_right, loop_buff->buffer, data_size - len_right);
+                }
+            }
+
+            LOGD("Head = %d, Tail = %d, Lenght = %d / %d", loop_buff->head, loop_buff->tail,
+                data_size, loop_buff->size);
+            log_hex("DATA", buff, data_size);
+            free(buff);
+            buff = NULL;
+        }
+    }
+    pthread_mutex_unlock(&loop_buff->mutex);
+}
+