Add mbtk_loopbuff and rtp support.

Change-Id: Idc80af4efb8ff76c4afc59fdf1d3896b453e6ff4
diff --git a/mbtk/libmbtk_lib/audio/mbtk_pcm_stream.c b/mbtk/libmbtk_lib/audio/mbtk_pcm_stream.c
index 40f89e5..9e5f8ce 100755
--- a/mbtk/libmbtk_lib/audio/mbtk_pcm_stream.c
+++ b/mbtk/libmbtk_lib/audio/mbtk_pcm_stream.c
@@ -1,3 +1,21 @@
+/*
+*    mbtk_pcm_stream.c
+*
+*    MBTK audio playback/record PCM source.
+*
+*/
+/******************************************************************************
+
+                          EDIT HISTORY FOR FILE
+
+  WHEN        WHO       WHAT,WHERE,WHY
+--------    --------    -------------------------------------------------------
+2024/03/23     LiuBin      Initial version.
+2024/10/15     LiuBin      Add PA and volume control API.
+2024/11/30     LiuBin      Add get/send PCM from/to the end of voice(RTP).
+
+******************************************************************************/
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -78,28 +96,28 @@
     int len, frames = 0;
     char buff[MBTK_PCM_WB_BUF_SIZE];
 
-    audio_info->info.recorder.state = AUDIO_RECORDER_STATE_RUNNING;
-    pthread_mutex_init(&audio_info->info.recorder.mutex, NULL);
-    pthread_cond_init(&audio_info->info.recorder.cond, NULL);
+    audio_info->recorder.state = AUDIO_RECORDER_STATE_RUNNING;
+    pthread_mutex_init(&audio_info->recorder.mutex, NULL);
+    pthread_cond_init(&audio_info->recorder.cond, NULL);
 
     while (TRUE) {
         /* Playback loop */
-        pthread_mutex_lock(&audio_info->info.recorder.mutex);
-        if(audio_info->info.recorder.state == AUDIO_RECORDER_STATE_STOP) {
+        pthread_mutex_lock(&audio_info->recorder.mutex);
+        if(audio_info->recorder.state == AUDIO_RECORDER_STATE_STOP) {
             LOGD("Stop recorder...");
-            pthread_mutex_unlock(&audio_info->info.recorder.mutex);
+            pthread_mutex_unlock(&audio_info->recorder.mutex);
             break;
-        } else if(audio_info->info.recorder.state == AUDIO_RECORDER_STATE_PAUSE) {
-            pthread_cond_wait(&audio_info->info.recorder.cond, &audio_info->info.recorder.mutex);
-            pthread_mutex_unlock(&audio_info->info.recorder.mutex);
+        } else if(audio_info->recorder.state == AUDIO_RECORDER_STATE_PAUSE) {
+            pthread_cond_wait(&audio_info->recorder.cond, &audio_info->recorder.mutex);
+            pthread_mutex_unlock(&audio_info->recorder.mutex);
             continue;
         } else {
-            pthread_mutex_unlock(&audio_info->info.recorder.mutex);
+            pthread_mutex_unlock(&audio_info->recorder.mutex);
         }
 
         //record the needed format stream from the device.
         //only read pcm stream, no send command.
-        len = audio_info->info.recorder.stream_in->read(audio_info->info.recorder.stream_in, buff,
+        len = audio_info->recorder.stream_in->read(audio_info->recorder.stream_in, buff,
                     audio_info->playback_size);
         if (len <= 0) {
             LOGE("%s: error reading!", __FUNCTION__);
@@ -108,45 +126,44 @@
 
         AUDIO_LOG("Recorder data : len - %d", len);
 
-        if(audio_info->info.recorder.recorder_cb) {
-            audio_info->info.recorder.recorder_cb(buff, len);
+        if(audio_info->recorder.recorder_cb) {
+            audio_info->recorder.recorder_cb(buff, len);
         }
 
-        LOGD("%s: No.%d frame playback.", __FUNCTION__, ++frames);
+        AUDIO_LOG("%s: No.%d frame playback.", __FUNCTION__, ++frames);
     }
 
 
 thread_end:
-    pthread_mutex_destroy(&audio_info->info.recorder.mutex);
-    pthread_cond_destroy(&audio_info->info.recorder.cond);
+    pthread_mutex_destroy(&audio_info->recorder.mutex);
+    pthread_cond_destroy(&audio_info->recorder.cond);
 
-    audio_info->info.recorder.stream_in->common.standby(&audio_info->info.recorder.stream_in->common);
-    audio_info->audio_ahw_dev_ubus->close_input_stream(audio_info->audio_ahw_dev_ubus, audio_info->info.recorder.stream_in);
+    audio_info->recorder.stream_in->common.standby(&audio_info->recorder.stream_in->common);
+    audio_info->audio_ahw_dev_ubus->close_input_stream(audio_info->audio_ahw_dev_ubus, audio_info->recorder.stream_in);
     VCMDeinit();//close the fd of audiostub_ctl when exit the thread.
-    audio_info->info.recorder.stream_in = NULL;
+    audio_info->recorder.stream_in = NULL;
     LOGD("%s: finished pcm playback.", __FUNCTION__);
 
     // Notify audio recorder data end.
-    if(audio_info->info.recorder.recorder_cb) {
-        audio_info->info.recorder.recorder_cb(NULL, 0);
+    if(audio_info->recorder.recorder_cb) {
+        audio_info->recorder.recorder_cb(NULL, 0);
     }
     return;
 }
 
 
-static int config_parameters(mbtk_audio_direction_enum direction, mbtk_audio_sample_rate_enum NBWB)
+// srcdst = 1;/* 0-None, 1-Near end, 2-Far end, 3-Both ends */
+// priority = 1;/* 0-Do not combine(override), 1-Combine */
+// dest = 1;/* 0-Near codec, 1-Near Vocoder */
+static int config_parameters(mbtk_audio_direction_enum direction, mbtk_audio_sample_rate_enum NBWB,
+                unsigned int srcdst, unsigned int priority, unsigned int dest)
 {
-    unsigned int srcdst, priority, dest;
     char kvpair[128];
     struct str_parms *param = NULL;
     int data[5];
     const char *key = NULL;
     bool update_vcm = false;
 
-    srcdst = 1;/* 0-None, 1-Near end, 2-Far end, 3-Both ends */
-    priority = 1;/* 0-Do not combine(override), 1-Combine */
-    dest = 1;/* 0-Near codec, 1-Near Vocoder */
-
     if(direction == MBTK_AUDIO_DIRECTION_OUTPUT){//output
         if(NBWB == MBTK_AUDIO_SAMPLE_RATE_8000)
             audio_info->playback_size = MBTK_PCM_NB_BUF_SIZE;
@@ -272,7 +289,7 @@
     return 0;
 }
 
-int mbtk_audio_pcm_play_start()
+int audio_pcm_play_start(unsigned int srcdst, unsigned int priority, unsigned int dest)
 {
     if(!audio_info) {
         LOGE("Not inited.");
@@ -284,18 +301,18 @@
         return -1;
     }
 
-    config_parameters(MBTK_AUDIO_DIRECTION_OUTPUT, audio_info->sample_rate);
+    config_parameters(MBTK_AUDIO_DIRECTION_OUTPUT, audio_info->sample_rate, srcdst, priority, dest);
 
     int rc = audio_info->audio_ahw_dev_ubus->open_output_stream(audio_info->audio_ahw_dev_ubus, 0,
             audio_info->audio_ahw_dev_ubus->get_supported_devices(audio_info->audio_ahw_dev_ubus),
-            AUDIO_OUTPUT_FLAG_DIRECT, NULL, &(audio_info->info.play.stream_out), 0);
+            AUDIO_OUTPUT_FLAG_DIRECT, NULL, &(audio_info->play.stream_out), 0);
     if (rc < 0) {
         LOGE("Open output device fail:%d", rc);
         goto play_start_fail;
     }
 
     audio_info->direction = MBTK_AUDIO_DIRECTION_OUTPUT;
-    audio_info->info.play.buff_remain_len = 0;
+    audio_info->play.buff_remain_len = 0;
     audio_pcm_write_count = 0;
 
     return 0;
@@ -304,6 +321,39 @@
     return -1;
 }
 
+// Send PCM to the other end of the voice.
+int mbtk_audio_voice_pcm_playback_start()
+{
+    // direction = 0;/* 0-play, 1-record */
+    // type = 0/1; /* 0:PCM_NB_BUF_SIZE, 1:PCM_WB_BUF_SIZE */
+    // srcdst = 2;/* 0-None, 1-Near end, 2-Far end, 3-Both ends */
+    // priority = 0;/* 0-Do not combine(override), 1-Combine */
+    // dest = 0;/* 0-Near codec, 1-Near Vocoder */
+    return audio_pcm_play_start(2, 0, 0);
+#if 0
+    if(!audio_info) {
+        LOGE("Not inited.");
+        return -1;
+    }
+
+    if(!audio_info->audio_ahw_dev_ubus) {
+        LOGE("audio_info->audio_ahw_dev_ubus is NULL.");
+        return -1;
+    }
+
+    config_parameters(MBTK_AUDIO_DIRECTION_OUTPUT, audio_info->sample_rate, 2, 0, 0);
+    audio_info->play.is_voip = TRUE;
+
+    return 0;
+#endif
+}
+
+// Send PCM to location SPK.
+int mbtk_audio_pcm_play_start()
+{
+    return audio_pcm_play_start(1, 1, 1);
+}
+
 int mbtk_audio_pcm_play_data_send(const void* data,uint32 data_len)
 {
     UNUSED(data);
@@ -314,25 +364,25 @@
         return -1;
     }
 
-    if(!audio_info->info.play.stream_out) {
+    if(!audio_info->play.stream_out) {
         LOGE("Output device not open.");
         return -1;
     }
 
     uint32 index = 0;
     // There are remaining data from the previous package。
-    if(audio_info->info.play.buff_remain_len > 0) {
+    if(audio_info->play.buff_remain_len > 0) {
         // Too less for one package.
-        if(data_len + audio_info->info.play.buff_remain_len < audio_info->playback_size) {
+        if(data_len + audio_info->play.buff_remain_len < audio_info->playback_size) {
             AUDIO_LOG("Save remain data : len - %d", data_len);
-            memcpy(audio_info->info.play.buff_remain + audio_info->info.play.buff_remain_len, data, data_len);
-            audio_info->info.play.buff_remain_len += data_len;
+            memcpy(audio_info->play.buff_remain + audio_info->play.buff_remain_len, data, data_len);
+            audio_info->play.buff_remain_len += data_len;
             return data_len;
         } else {
-            AUDIO_LOG("Write remain data : %d + %d", audio_info->info.play.buff_remain_len, audio_info->playback_size - audio_info->info.play.buff_remain_len);
-            memcpy(audio_info->info.play.buff_remain + audio_info->info.play.buff_remain_len, data, audio_info->playback_size - audio_info->info.play.buff_remain_len);
+            AUDIO_LOG("Write remain data : %d + %d", audio_info->play.buff_remain_len, audio_info->playback_size - audio_info->play.buff_remain_len);
+            memcpy(audio_info->play.buff_remain + audio_info->play.buff_remain_len, data, audio_info->playback_size - audio_info->play.buff_remain_len);
 
-            int rc = audio_info->info.play.stream_out->write(audio_info->info.play.stream_out, audio_info->info.play.buff_remain, audio_info->playback_size);
+            int rc = audio_info->play.stream_out->write(audio_info->play.stream_out, audio_info->play.buff_remain, audio_info->playback_size);
             if (rc < 0) {
                 LOGE("%s: error writing (child).", __FUNCTION__);
                 goto send_fail;
@@ -357,14 +407,14 @@
                 }
             }
 
-            index += (audio_info->playback_size - audio_info->info.play.buff_remain_len);
-            audio_info->info.play.buff_remain_len = 0;
+            index += (audio_info->playback_size - audio_info->play.buff_remain_len);
+            audio_info->play.buff_remain_len = 0;
         }
     }
 
     while(data_len - index >= audio_info->playback_size) {
         AUDIO_LOG("Package : %d -> %d", index, index + audio_info->playback_size - 1);
-        int rc = audio_info->info.play.stream_out->write(audio_info->info.play.stream_out, (const char*)data + index, audio_info->playback_size);
+        int rc = audio_info->play.stream_out->write(audio_info->play.stream_out, (const char*)data + index, audio_info->playback_size);
         if (rc < 0) {
             LOGE("%s: error writing (child).", __FUNCTION__);
             goto send_fail;
@@ -380,8 +430,8 @@
     // Save to buffer audio_info->play_buff_remain
     if(data_len - index > 0) {
         AUDIO_LOG("Save remain data : len - %d", data_len - index);
-        memcpy(audio_info->info.play.buff_remain, data + index, data_len - index);
-        audio_info->info.play.buff_remain_len = data_len - index;
+        memcpy(audio_info->play.buff_remain, data + index, data_len - index);
+        audio_info->play.buff_remain_len = data_len - index;
     }
 
     return data_len;
@@ -396,20 +446,20 @@
         return -1;
     }
 
-    if(!audio_info->info.play.stream_out) {
+    if(!audio_info->play.stream_out) {
         LOGE("Output device not open.");
         return -1;
     }
 
     // Write last package.
-    if(audio_info->info.play.buff_remain_len > 0) {
+    if(audio_info->play.buff_remain_len > 0) {
         char buf[MBTK_PCM_WB_BUF_SIZE];
         memset(buf, 0x00, sizeof(buf));
-        memcpy(buf, audio_info->info.play.buff_remain, audio_info->info.play.buff_remain_len);
+        memcpy(buf, audio_info->play.buff_remain, audio_info->play.buff_remain_len);
 
-        LOGD("len %d is smaller than needed %d, so fill the buffer with 0.", audio_info->info.play.buff_remain_len, audio_info->playback_size);
+        LOGD("len %d is smaller than needed %d, so fill the buffer with 0.", audio_info->play.buff_remain_len, audio_info->playback_size);
 
-        int rc = audio_info->info.play.stream_out->write(audio_info->info.play.stream_out, buf, audio_info->playback_size);
+        int rc = audio_info->play.stream_out->write(audio_info->play.stream_out, buf, audio_info->playback_size);
         if (rc < 0) {
             LOGE("%s: error writing (child).", __FUNCTION__);
             //goto send_fail;
@@ -417,7 +467,7 @@
             LOGW("%s: wrote less than buffer size, rc=%d.", __FUNCTION__, rc);
             //goto send_fail;
         }
-        audio_info->info.play.buff_remain_len = 0;
+        audio_info->play.buff_remain_len = 0;
     }
 
     // Close PA
@@ -427,15 +477,15 @@
 
     vcm_playback_drain(80);//wait for drain the AP audiostub queue.
     usleep(80000);//delay 80ms until DSP play out its buffered data.
-    audio_info->info.play.stream_out->common.standby(&(audio_info->info.play.stream_out->common));
-    audio_info->audio_ahw_dev_ubus->close_output_stream(audio_info->audio_ahw_dev_ubus, audio_info->info.play.stream_out);
+    audio_info->play.stream_out->common.standby(&(audio_info->play.stream_out->common));
+    audio_info->audio_ahw_dev_ubus->close_output_stream(audio_info->audio_ahw_dev_ubus, audio_info->play.stream_out);
 
-    audio_info->info.play.stream_out = NULL;
+    audio_info->play.stream_out = NULL;
     return 0;
 }
 
-
-int mbtk_audio_pcm_recorder_start(mbtk_recorder_callback_func recorder_cb)
+static int audio_pcm_recorder_start(mbtk_recorder_callback_func recorder_cb,
+                unsigned int srcdst, unsigned int priority, unsigned int dest)
 {
     if(!audio_info) {
         LOGE("Not inited.");
@@ -447,25 +497,25 @@
         return -1;
     }
 
-    if(audio_info->info.recorder.state != AUDIO_RECORDER_STATE_STOP) {
+    if(audio_info->recorder.state != AUDIO_RECORDER_STATE_STOP) {
         LOGW("Audio is recorder...");
         return -1;
     }
 
-    config_parameters(MBTK_AUDIO_DIRECTION_INPUT, audio_info->sample_rate);
+    config_parameters(MBTK_AUDIO_DIRECTION_INPUT, audio_info->sample_rate, srcdst, priority, dest);
 
     VCMInit();
 
     int rc = audio_info->audio_ahw_dev_ubus->open_input_stream(audio_info->audio_ahw_dev_ubus, 0,
                 audio_info->audio_ahw_dev_ubus->get_supported_devices(audio_info->audio_ahw_dev_ubus),
-                NULL, &(audio_info->info.recorder.stream_in), 0, 0, AUDIO_SOURCE_VOICE_CALL);
+                NULL, &(audio_info->recorder.stream_in), 0, 0, AUDIO_SOURCE_VOICE_CALL);
     if (rc < 0) {
         LOGE("Open input device fail:%d", rc);
         goto recorder_start_fail;
     }
 
     audio_info->direction = MBTK_AUDIO_DIRECTION_INPUT;
-    audio_info->info.recorder.recorder_cb = recorder_cb;
+    audio_info->recorder.recorder_cb = recorder_cb;
 
     pthread_attr_t thread_attr;
     pthread_attr_init(&thread_attr);
@@ -486,32 +536,70 @@
     return -1;
 }
 
+// Get PCM from the other end of the voice.
+int mbtk_audio_voice_pcm_record_start(mbtk_recorder_callback_func recorder_cb)
+{
+    // direction = 1;/* 0-play, 1-record */
+    // type = 0/1; /* 0:PCM_NB_BUF_SIZE, 1:PCM_WB_BUF_SIZE */
+    // srcdst = 2;/* 0-None, 1-Near end, 2-Far end, 3-Both ends */
+    // priority = 0;/* 0-Do not combine(override), 1-Combine */
+    // dest = 0;/* 0-Near codec, 1-Near Vocoder */
+    return audio_pcm_recorder_start(recorder_cb, 2, 0, 0);
+#if 0
+    if(!audio_info) {
+        LOGE("Not inited.");
+        return -1;
+    }
+
+    if(!audio_info->audio_ahw_dev_ubus) {
+        LOGE("audio_info->audio_ahw_dev_ubus is NULL.");
+        return -1;
+    }
+
+    if(audio_info->recorder.state != AUDIO_RECORDER_STATE_STOP) {
+        LOGW("Audio is recorder...");
+        return -1;
+    }
+
+    config_parameters(MBTK_AUDIO_DIRECTION_INPUT, audio_info->sample_rate, 2, 0, 0);
+    audio_info->recorder.is_voip = TRUE;
+
+    return 0;
+#endif
+}
+
+// Get PCM from location MIC.
+int mbtk_audio_pcm_recorder_start(mbtk_recorder_callback_func recorder_cb)
+{
+    return audio_pcm_recorder_start(recorder_cb, 1, 1, 1);
+}
+
 int mbtk_audio_pcm_recorder_pause()
 {
     int result = 0;
-    pthread_mutex_lock(&audio_info->info.recorder.mutex);
-    if(audio_info->info.recorder.state == AUDIO_RECORDER_STATE_RUNNING) {
-        audio_info->info.recorder.state = AUDIO_RECORDER_STATE_PAUSE;
+    pthread_mutex_lock(&audio_info->recorder.mutex);
+    if(audio_info->recorder.state == AUDIO_RECORDER_STATE_RUNNING) {
+        audio_info->recorder.state = AUDIO_RECORDER_STATE_PAUSE;
     } else {
         result = -1;
-        LOGW("Audio state : %d", audio_info->info.recorder.state);
+        LOGW("Audio state : %d", audio_info->recorder.state);
     }
-    pthread_mutex_unlock(&audio_info->info.recorder.mutex);
+    pthread_mutex_unlock(&audio_info->recorder.mutex);
     return result;
 }
 
 int mbtk_audio_pcm_recorder_resume()
 {
     int result = 0;
-    pthread_mutex_lock(&audio_info->info.recorder.mutex);
-    if(audio_info->info.recorder.state == AUDIO_RECORDER_STATE_PAUSE) {
-        audio_info->info.recorder.state = AUDIO_RECORDER_STATE_RUNNING;
-        pthread_cond_signal(&audio_info->info.recorder.cond);
+    pthread_mutex_lock(&audio_info->recorder.mutex);
+    if(audio_info->recorder.state == AUDIO_RECORDER_STATE_PAUSE) {
+        audio_info->recorder.state = AUDIO_RECORDER_STATE_RUNNING;
+        pthread_cond_signal(&audio_info->recorder.cond);
     } else {
         result = -1;
-        LOGW("Audio state : %d", audio_info->info.recorder.state);
+        LOGW("Audio state : %d", audio_info->recorder.state);
     }
-    pthread_mutex_unlock(&audio_info->info.recorder.mutex);
+    pthread_mutex_unlock(&audio_info->recorder.mutex);
     return result;
 }
 
@@ -519,13 +607,13 @@
 int mbtk_audio_pcm_recorder_stop()
 {
     int result = 0;
-    pthread_mutex_lock(&audio_info->info.recorder.mutex);
-    if(audio_info->info.recorder.state == AUDIO_RECORDER_STATE_PAUSE || audio_info->info.recorder.state == AUDIO_RECORDER_STATE_RUNNING) {
-        if(audio_info->info.recorder.state == AUDIO_RECORDER_STATE_PAUSE) {
-            pthread_cond_signal(&audio_info->info.recorder.cond);
+    pthread_mutex_lock(&audio_info->recorder.mutex);
+    if(audio_info->recorder.state == AUDIO_RECORDER_STATE_PAUSE || audio_info->recorder.state == AUDIO_RECORDER_STATE_RUNNING) {
+        if(audio_info->recorder.state == AUDIO_RECORDER_STATE_PAUSE) {
+            pthread_cond_signal(&audio_info->recorder.cond);
         }
-        audio_info->info.recorder.state = AUDIO_RECORDER_STATE_STOP;
-        pthread_mutex_unlock(&audio_info->info.recorder.mutex);
+        audio_info->recorder.state = AUDIO_RECORDER_STATE_STOP;
+        pthread_mutex_unlock(&audio_info->recorder.mutex);
 
         LOGD("Waitting recorder thread exit...");
         if (pthread_join(recorder_thread_play, NULL)) {
@@ -534,9 +622,9 @@
         }
         LOGD("Recorder thread exit success.");
     } else {
-        pthread_mutex_unlock(&audio_info->info.recorder.mutex);
+        pthread_mutex_unlock(&audio_info->recorder.mutex);
         result = -1;
-        LOGW("Audio state : %d", audio_info->info.recorder.state);
+        LOGW("Audio state : %d", audio_info->recorder.state);
     }
 
     return result;