[Feature][ZXW-452]merge P54U02 version
Only Configure: No
Affected branch: master
Affected module: unknow
Is it affected on both ZXIC and MTK: only ZXIC
Self-test: Yes
Doc Update: No
Change-Id: I17e6795ab66e2b9d1cbbfec4b7c0028d666e177d
diff --git a/ap/lib/libvoice/voice_buffer.c b/ap/lib/libvoice/voice_buffer.c
new file mode 100755
index 0000000..ba4e33e
--- /dev/null
+++ b/ap/lib/libvoice/voice_buffer.c
@@ -0,0 +1,561 @@
+/*****************************************************************************
+** °æÈ¨ËùÓÐ (C)2015, ÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾¡£
+**
+** ÎļþÃû³Æ: voice_buffer.c
+** Îļþ±êʶ:
+** ÄÚÈÝÕªÒª:
+** ʹÓ÷½·¨:
+**
+** ÐÞ¸ÄÈÕÆÚ °æ±¾ºÅ Ð޸ıê¼Ç ÐÞ¸ÄÈË ÐÞ¸ÄÄÚÈÝ
+** -----------------------------------------------------------------------------
+** 2023/07/18 V1.0 Create xxq ´´½¨
+**
+* ******************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <stdint.h>
+
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <signal.h>
+
+#include <poll.h>
+#include <pthread.h>
+#include <semaphore.h>
+
+#include <linux/volte_drv.h>
+
+//#define VB_DATA_LOSS_TEST
+
+#define VB_MAX_INT 0x7fffffff
+#define VB_MIN_INT 0 //(0-2<<31)//
+#define VB_INT_OVERFLOW(x) if((x < VB_MIN_INT)||(x > VB_MAX_INT)) x = 0;
+
+#define _TX_RX_DATA_FROM_FILE //test use
+#define VB_FUNC_DEBUG //DEBUG use
+
+#define VBUFFER_DEV_NAME "/dev/voice_buffer_dev"
+#define VBUFFER_DEV_FLAGS O_RDWR //O_RDWR | O_SYNC
+
+typedef int (vb_thread_proc)(void*);
+typedef int (vb_ext_rx_tx_func)(void*,int);
+
+struct vb_info_t
+{
+ int fd;
+ pthread_t rx_thread;
+ pthread_t tx_thread;
+ int quit;
+ char *tx_buf;
+ char *rx_buf;
+ int buf_size;
+ vb_ext_rx_tx_func *ext_rx_func;
+ vb_ext_rx_tx_func *ext_tx_func;
+ sem_t read_sem;
+ sem_t write_sem;
+#ifdef _TX_RX_DATA_FROM_FILE
+ char *tx_filename;
+ char *rx_filename;
+ FILE *tx_file;
+ FILE *rx_file;
+ int tx_filesize;
+ int rx_filesize;
+#endif
+};
+
+struct vb_info_t vb_rec = {0};
+
+int tx_optcount = 0;
+int rx_optcount = 0;
+int first_rderr_flag = 0;
+int first_wrerr_flag = 0;
+
+void vb_signal_back_func(int signum)
+{
+ sem_post(&vb_rec.read_sem);
+ sem_post(&vb_rec.write_sem);
+}
+
+int voice_buffer_open(void)
+{
+ int fd;
+ int oflags;
+
+ fd = open(VBUFFER_DEV_NAME, VBUFFER_DEV_FLAGS);
+ printf("%s: fd=%d!\n", __func__, fd);
+
+ signal(SIGIO, vb_signal_back_func); //Ó¦ÓóÌÐò×¢²áÐźŴ¦Àíº¯Êý£¬SIGIO±íʾIOÓÐÊý¾Ý¿É¹©¶ÁÈ¡
+ fcntl(fd, F_SETOWN, getpid());
+ oflags = fcntl(fd, F_GETFL);
+ fcntl(fd, F_SETFL, oflags|FASYNC);
+
+ sem_init(&vb_rec.read_sem, 0, 0);
+ sem_init(&vb_rec.write_sem, 0, 0);
+
+ tx_optcount = 0;
+ rx_optcount = 0;
+
+ first_rderr_flag = 0;
+ first_wrerr_flag = 0;
+
+ return fd;
+}
+
+int voice_buffer_close(int fd)
+{
+ int ret = 0;
+
+ if(fd >= 0){
+ ret = close(fd);
+ }
+ else{
+ printf("%s: fd invalid, return!\n", __func__);
+ return -ENOENT;
+ }
+
+ vb_rec.fd = -1;
+ sem_destroy(&vb_rec.read_sem);
+ sem_destroy(&vb_rec.write_sem);
+ printf("%s, first_rderr_flag=%d, first_wrerr_flag=%d, tx_optcount=%d, rx_optcount=%d\n", __func__, first_rderr_flag, first_wrerr_flag, tx_optcount, rx_optcount);
+
+ return ret;
+}
+
+
+int voice_buffer_write(int fd, unsigned char *pdata, unsigned int len)
+{
+ int ret;
+ static struct timespec pre_wtime = {0};
+ struct timespec cur_wtime = {0};
+
+ if(fd >= 0){
+ sem_wait(&vb_rec.write_sem);
+ clock_gettime(CLOCK_REALTIME, &cur_wtime);
+ //printf("%s: tv_sec=%d, tv_nsec=%d\r\n", __func__, cur_wtime.tv_sec, cur_wtime.tv_nsec);
+
+ ret = write(fd, pdata, len);
+ }
+ else{
+ printf("%s: fd invalid, return!\n",__func__);
+ return -ENOENT;
+ }
+ return ret;
+}
+
+int voice_buffer_read(int fd, unsigned char *pdata, unsigned int len)
+{
+ int ret;
+ static struct timespec pre_rtime = {0};
+ struct timespec cur_rtime = {0};
+
+ if(fd >= 0){
+ sem_wait(&vb_rec.read_sem);
+ clock_gettime(CLOCK_REALTIME, &cur_rtime);
+ //printf("%s: tv_sec=%d, tv_nsec=%d\r\n", __func__, cur_rtime.tv_sec, cur_rtime.tv_nsec);
+
+ ret = read(fd, pdata, len);
+ }
+ else{
+ printf("%s: fd invalid, return!\n", __func__);
+ return -ENOENT;
+ }
+
+ return ret;
+}
+
+int voice_buffer_ioctl(int fd, unsigned int cmd, void *pvalue)
+{
+ int ret = 0;
+
+ if(fd >= 0){
+ ret = ioctl(fd, cmd, pvalue);
+ }
+ else{
+ printf("%s: fd invalid, return\n", __func__);
+ return -ENOENT;
+ }
+
+ return ret;
+}
+
+static int vb_rx_thread_func(void *arg)
+{
+ int ret = 0;
+
+ char* buf = vb_rec.rx_buf;
+ int size = vb_rec.buf_size;
+ unsigned int bytes_read = 0;
+ int r_size = 0;
+
+ printf("%s: start size=%d!\n", __func__, size);
+ memset(buf, 0, size);
+
+ while(!vb_rec.quit){
+ rx_optcount ++;
+ VB_INT_OVERFLOW(rx_optcount);
+
+ if((rx_optcount % 1000) == 0){
+ printf("%s: rx_optcount=%d!\n", __func__, rx_optcount);
+
+ if(rx_optcount == 1000000)
+ rx_optcount = 0;
+ }
+
+ //read from ps
+ r_size = voice_buffer_read(vb_rec.fd, buf, size);
+
+ if(r_size <= 0){
+ first_rderr_flag++;
+
+ VB_INT_OVERFLOW(first_rderr_flag);
+
+ if(first_rderr_flag == 1){
+ printf( "%s: error reading data!\n", __func__);
+ }
+ if((first_rderr_flag % 500) == 0){
+ printf("%s: first_rderr_flag=%d!\n", __func__, first_rderr_flag);
+ }
+
+ continue ;
+ }
+ else{
+ first_rderr_flag = 0;
+ }
+
+#ifdef _TX_RX_DATA_FROM_FILE
+ if(vb_rec.rx_file != NULL)
+ {
+#if 0
+ static int i=0;
+ i++;
+ if (i==50) {
+ printf("vb_rx_thread_func buf[%d]=%d\n",i,buf[i]);
+ i=0;
+ }
+#endif
+ //if(fwrite(buf, 1, size, vb_rec.rx_file) != size){//µ¥¸ö×Ö½ÚдÈ룬ÎļþûÊý¾Ý
+ if(fwrite(buf, size, 1, vb_rec.rx_file) != 1){
+ printf("%s: Error fwrite\n", __func__);
+ //break;
+ }
+ else{
+ bytes_read += size;
+
+ if(bytes_read >= vb_rec.rx_filesize){
+ //fseek(vb_rec.rx_file, 0, SEEK_SET);//дÈë²»ÏÞÖÆÎļþ´óС
+ }
+ }
+ }
+#endif
+ }
+
+ return 0;
+}
+
+static int vb_tx_thread_func(void *arg)
+{
+ int ret = 0;
+
+ int num_read = 0;
+ char* buf = vb_rec.tx_buf;
+ int size = vb_rec.buf_size;
+ int w_size = 0;
+
+ printf("%s: start size=%d!\n", __func__, size);
+
+#ifndef VB_DATA_LOSS_TEST
+ memset(buf, 0, size);
+#endif
+
+ while(!vb_rec.quit){
+#if defined (_TX_RX_DATA_FROM_FILE) && !defined (VB_DATA_LOSS_TEST)
+
+ if(vb_rec.tx_file != NULL)
+ {
+ //num_read = fread(buf, 1, size, vb_rec.tx_file);
+ num_read = fread(buf, size, 1, vb_rec.tx_file);
+ if (num_read <= 0) {
+ printf("%s: vb_rec.tx_file read end\n",__func__);
+ // no data
+ //fseek(vb_rec.tx_file, 0, SEEK_SET);
+ }
+ }
+#endif
+
+ tx_optcount ++;
+ VB_INT_OVERFLOW(tx_optcount);
+
+ if((tx_optcount%1000) == 0){
+ printf("%s: tx_optcount=%d!\n", __func__, tx_optcount);
+
+ if(tx_optcount == 1000000)
+ tx_optcount = 0;
+ }
+
+ //write to ps
+ w_size = voice_buffer_write(vb_rec.fd, buf, size);
+
+ if(w_size <= 0){
+ first_wrerr_flag++;
+ VB_INT_OVERFLOW(first_wrerr_flag);
+
+ if(first_wrerr_flag ==1){
+ printf("%s: error writing data!\n", __func__);
+ }
+ if((first_wrerr_flag % 500) == 0){
+ printf("%s: first_wrerr_flag=%d!\n", __func__, first_wrerr_flag);
+ }
+
+ continue;
+ }
+ else{
+ first_wrerr_flag = 0;
+ }
+ }
+
+ return 0;
+}
+
+static int vb_thread_create( const char *name,pthread_t *thread_t, vb_thread_proc *proc,
+ int stack_size, unsigned priority,void *arg )
+{
+ pthread_attr_t thread_attr;
+ int ret = 0;
+ int default_size = 0;
+
+ struct sched_param param;
+ int policy = SCHED_FIFO;
+
+ /* Set default stack size */
+ //stack_size = 8*1024;//32*1024;
+ printf("%s: start!\n", __func__);
+
+ /* Init thread attributes */
+ pthread_attr_init(&thread_attr);
+ //pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
+ /*
+ ret = pthread_attr_setstacksize(&thread_attr, stack_size);
+ if (ret != 0)
+ {
+
+ printf("%s: pthread_attr_setstacksize(%d) fail,ret=%d! \n",__func__,stack_size,ret);
+ pthread_attr_destroy(&thread_attr);
+ return ret;
+ }
+ */
+
+ /* Create the thread. */
+
+ ret = pthread_create( thread_t, &thread_attr,proc, arg);
+ if(ret != 0){
+ printf("%s: pthread_create fail,ret=%d!\n", __func__, ret);
+
+ pthread_attr_destroy(&thread_attr);
+
+ return ret;
+ }
+
+ pthread_attr_getstacksize(&thread_attr, &default_size);
+ printf("%s: pthread_attr_getstacksize(%d)!\n", __func__, default_size);
+
+ //pthread_detach(rec->thread);
+ /*
+ memset(¶m, 0, sizeof(param));
+ //param.sched_priority =36;
+ param.sched_priority = priority;
+ pthread_setschedparam(thread_t, policy, ¶m);
+ */
+ pthread_attr_destroy(&thread_attr);
+
+ printf("%s: end\n", __func__);
+
+ return 0;
+}
+
+//Start stream
+int vbuffer_stream_start(void)
+{
+ int ret = 0;
+
+ //voice_buffer_open
+ int fs = 0;
+ int buf_size = 0;
+ printf("Starting vb stream\n");
+ tx_optcount = 0;
+ rx_optcount = 0;
+ int* buf_int;
+ int i = 0;
+
+ vb_rec.fd = voice_buffer_open();
+ if(vb_rec.fd < 0){
+ printf("%s: vb open fail, fd=%d\n", __func__, vb_rec.fd);
+ ret = -1;
+ goto err;
+ }
+
+ ret = ioctl(vb_rec.fd, VOICE_IOCTL_GET_FS, &fs);
+ if(ret){
+ printf("%s: VOICE_IOCTL_GET_FS fd=%d,ret=%d.\n", __func__, vb_rec.fd, ret);
+ goto err;
+ }
+
+ if(8000 == fs)
+ buf_size = 320;
+ else if(16000 == fs)
+ buf_size = 640;
+ else{
+ buf_size = 0;
+ printf("%s: fs is error, buf_size=%d\n", __func__, buf_size);
+ goto err;
+ }
+
+#ifdef _TX_RX_DATA_FROM_FILE
+ printf("%s: open tx and rx file\n", __func__);
+
+ if(8000 == fs)
+ vb_rec.tx_filename = "/mnt/userdata/tx8.pcm";
+ else if(16000 == fs)
+ vb_rec.tx_filename = "/mnt/userdata/tx16.pcm";
+
+ vb_rec.tx_file = fopen(vb_rec.tx_filename, "rb");
+ if(!vb_rec.tx_file){
+ printf("Unable to open file '%s'\n", vb_rec.tx_filename);
+ //return 1;
+ }
+
+ if(8000 == fs)
+ vb_rec.rx_filename = "/mnt/userdata/rx8.pcm";
+ else if(16000 == fs)
+ vb_rec.rx_filename = "/mnt/userdata/rx16.pcm";
+
+ vb_rec.rx_file = fopen(vb_rec.rx_filename, "wb");
+ if(!vb_rec.rx_file){
+ printf(stderr, "Unable to create file '%s'\n", vb_rec.rx_filename);
+ //return 1;
+ }
+
+ vb_rec.rx_filesize = 0x10000;
+ //vb_rec.buf_size = buf_size;
+#endif
+
+ vb_rec.rx_buf = (char*)malloc(buf_size);
+ if(!vb_rec.rx_buf){
+ printf("%s: malloc rx_buf fail\n", __func__);
+ goto err;
+ }
+
+ vb_rec.tx_buf = (char*)malloc(buf_size);
+ if(!vb_rec.tx_buf){
+ //free(vb_rec.rx_buf);
+ printf("%s: malloc tx_buf fail\n", __func__);
+ goto err;
+ }
+
+ vb_rec.buf_size = buf_size;
+
+#ifdef VB_DATA_LOSS_TEST//for test
+ buf_int = (int*)vb_rec.tx_buf;
+
+ for(i = 0; i < (buf_size / 4); i++){
+ *(buf_int + i) = i;
+ //buf_int[i] = i;
+ if(i > 0x1f)
+ printf("cap user: *(buf_int+%d)=%d\n", i, *(buf_int+i));
+ }
+#endif
+
+ vb_rec.quit = 0;
+
+ printf("%s: rx tx vb_thread_create start\n", __func__);
+ ret = vb_thread_create("vb_playback", &vb_rec.rx_thread, vb_rx_thread_func,
+ 4*1024, 36, NULL);
+ if(ret != 0){
+ printf("%s: rx vb_thread_create fail ret=%d\n", __func__, ret);
+ goto err;
+ }
+
+ printf("%s: rx vb_thread_create end\n", __func__);
+
+ ret = vb_thread_create("vb_record", &vb_rec.tx_thread, vb_tx_thread_func,
+ 4*1024, 36, NULL);
+ if(ret != 0){
+ printf("%s: tx vb_thread_create fail ret=%d\n", __func__, ret);
+ vb_rec.quit = 1;
+ pthread_join(vb_rec.rx_thread,NULL);
+ vb_rec.rx_thread = NULL;
+ goto err;
+ }
+
+ printf("%s: tx vb_thread_create end\n", __func__);
+
+ //vb_rec.quit = 0;
+ return 0;
+
+err:
+ if(vb_rec.rx_buf != NULL)
+ free(vb_rec.rx_buf);
+
+ if(vb_rec.tx_buf != NULL)
+ free(vb_rec.tx_buf);
+
+ if(vb_rec.fd >= 0)
+ voice_buffer_close(vb_rec.fd);
+
+ return ret;
+}
+
+//Stop stream
+int vbuffer_stream_stop(void)
+{
+ int ret = 0;
+ printf("%s: rx tx thread exit start\n", __func__);
+
+ vb_rec.quit = 1;
+ sem_post(&vb_rec.read_sem);
+ sem_post(&vb_rec.write_sem);
+
+ if(vb_rec.tx_thread){
+ pthread_join (vb_rec.tx_thread,NULL);
+ vb_rec.tx_thread = NULL;
+ printf("tx_thread exit end\n");
+ }
+
+ if(vb_rec.rx_thread){
+ pthread_join (vb_rec.rx_thread,NULL);
+ vb_rec.rx_thread = NULL;
+ printf("rx_thread exit end\n");
+ }
+
+ printf("%s: voice_buffer_close start\n", __func__);
+ ret = voice_buffer_close(vb_rec.fd);
+ if(ret != 0){
+ printf("%s: vb close fail\n", __func__);
+
+ return -1;
+ }
+
+#ifdef _TX_RX_DATA_FROM_FILE
+ if(vb_rec.tx_file != NULL){
+ fclose(vb_rec.tx_file);
+ printf("%s: vb close, close tx file\n", __func__);
+ }
+
+ if(vb_rec.rx_file != NULL){
+ fclose(vb_rec.rx_file);
+ printf("%s: vb close, close rx file\n", __func__);
+ }
+#endif
+
+ printf("Stopping vb stream end\n");
+
+ return 0;
+}
+