[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(&param, 0, sizeof(param));

+    //param.sched_priority =36;

+    param.sched_priority = priority;

+    pthread_setschedparam(thread_t, policy, &param);

+   */ 

+    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;

+}

+