Support audio I/O on TV code 93/289493/2
authorSuyeon Hwang <stom.hwang@samsung.com>
Thu, 9 Mar 2023 00:45:38 +0000 (09:45 +0900)
committerSuyeon Hwang <stom.hwang@samsung.com>
Thu, 9 Mar 2023 02:10:47 +0000 (11:10 +0900)
- Issue:
On TV, STT can not record voice with USB MIC.

- Solution:
In previous code, STT framework did not use audio I/O framework on TV
platform code. So, on TV, STT framework did not record sound using audio
I/O framework. This patch makes the framework use audio I/O framework on
TV. Through this patch, STT framework choose the recording source by
audio ID which is set by clients. Of course, even though this patch is
applied, the code for TV only will be still blocked in common image.

Change-Id: I45e68b614fd48a818c06822979738c0021e4532a
Signed-off-by: Suyeon Hwang <stom.hwang@samsung.com>
server/sttd_recorder.c

index 157d9dc..36577e6 100644 (file)
 #define FRAME_LENGTH 320
 #define BUFFER_LENGTH FRAME_LENGTH * 2
 
-static pthread_mutex_t sttd_audio_in_handle_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-#ifndef TV_BT_MODE
-static Ecore_Timer* g_audio_timer = NULL;
-#endif
 
 typedef enum {
        STTD_RECORDER_STATE_NONE = -1,
@@ -62,6 +57,11 @@ typedef struct {
        stte_audio_type_e       audio_type;
 } stt_recorder_s;
 
+
+static pthread_mutex_t sttd_audio_in_handle_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static Ecore_Timer* g_audio_timer = NULL;
+
 static stt_recorder_s* g_recorder = NULL;
 
 static stt_recorder_audio_cb   g_audio_cb;
@@ -388,7 +388,6 @@ int sttd_recorder_deinitialize()
 
 #ifdef TV_BT_MODE
        bt_hid_host_deinitialize();
-
        bt_product_deinit();
 #endif
 
@@ -416,8 +415,6 @@ int sttd_recorder_create(stte_audio_type_e type, int channel, unsigned int sampl
        }
 
        audio_in_h temp_in_h = NULL;
-
-#ifndef TV_BT_MODE
        audio_channel_e audio_ch;
        audio_sample_type_e audio_type;
 
@@ -445,17 +442,13 @@ int sttd_recorder_create(stte_audio_type_e type, int channel, unsigned int sampl
                SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to create audio handle : %d", ret);
                return STTD_ERROR_OPERATION_FAILED;
        }
-#endif
 
-       stt_recorder_s* recorder;
-       recorder = (stt_recorder_s*)calloc(1, sizeof(stt_recorder_s));
+       stt_recorder_s *recorder = (stt_recorder_s *)calloc(1, sizeof(stt_recorder_s));
        if (NULL == recorder) {
-#ifndef TV_BT_MODE
                if (temp_in_h) {
                        audio_in_destroy(temp_in_h);
                        temp_in_h = NULL;
                }
-#endif
                SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to allocate memory");
                return STTD_ERROR_OUT_OF_MEMORY;
        }
@@ -484,11 +477,9 @@ int sttd_recorder_destroy()
                return STTD_ERROR_INVALID_PARAMETER;
        }
 
-#ifndef TV_BT_MODE
-       int ret;
        if (STTD_RECORDER_STATE_RECORDING == g_recorder_state) {
                if (g_recorder->audio_h) {
-                       ret = audio_in_unprepare(g_recorder->audio_h);
+                       int ret = audio_in_unprepare(g_recorder->audio_h);
                        if (AUDIO_IO_ERROR_NONE != ret) {
                                SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to unprepare audioin : %d", ret);
                        }
@@ -498,18 +489,14 @@ int sttd_recorder_destroy()
        }
 
        if (g_recorder->audio_h) {
-               ret = audio_in_destroy(g_recorder->audio_h);
+               int ret = audio_in_destroy(g_recorder->audio_h);
                if (AUDIO_IO_ERROR_NONE != ret) {
                        SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to destroy audioin : %d", ret);
                }
                g_recorder->audio_h = NULL;
        }
 
-#else
-       if (STTD_RECORDER_STATE_RECORDING == g_recorder_state) {
-               g_recorder_state = STTD_RECORDER_STATE_READY;
-       }
-
+#ifdef TV_BT_MODE
        bt_hid_unset_audio_data_receive_cb();
 #endif
 
@@ -565,8 +552,7 @@ float get_volume_decibel(char* data, int size, stte_audio_type_e type)
        return db;
 }
 
-#ifndef TV_BT_MODE
-Eina_Bool __read_audio_func(void *data)
+Eina_Bool read_audio_func(void *data)
 {
        int read_byte = -1;
        static char g_buffer[BUFFER_LENGTH];
@@ -622,10 +608,9 @@ Eina_Bool __read_audio_func(void *data)
 
        return EINA_TRUE;
 }
-#endif
 
 #ifdef TV_BT_MODE
-bool __is_tct_app(const char* appid)
+static bool is_tct_app(const char* appid)
 {
        int cnt = 0;
        if (NULL == appid) {
@@ -642,13 +627,73 @@ bool __is_tct_app(const char* appid)
 
        return false;
 }
+
+static void start_recording_with_bt_rc_manually()
+{
+       int ret = -1;
+       int bt_retry = 0;
+       bool started = false;
+       while (5 > bt_retry) {
+               ret = bt_hid_rc_start_sending_voice(NULL);
+               if (BT_ERROR_NONE == ret) {
+                       SLOG(LOG_DEBUG, TAG_STTD, "[Recorder] Start bt audio");
+                       started = true;
+                       break;
+               } else if (BT_ERROR_NOW_IN_PROGRESS == ret) {
+                       SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail bt_hid_rc_start_sending_voice()");
+                       usleep(50000);
+                       bt_retry++;
+               } else {
+                       SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] bt_hid_rc_start_sending_voice(): ret(%d)", ret);
+                       break;
+               }
+       }
+
+       if (false == started) {
+               SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to start bt audio(%d)", ret);
+       }
+}
 #endif
 
+static int start_recording_with_audio_fw()
+{
+       int ret = audio_in_set_sound_stream_info(g_recorder->audio_h, g_stream_info_h);
+       if (AUDIO_IO_ERROR_NONE != ret) {
+               SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to set stream info");
+       }
+
+       ret = audio_in_prepare(g_recorder->audio_h);
+       if (AUDIO_IO_ERROR_NONE != ret) {
+               SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to start audio : %d", ret);
+               return STTD_ERROR_RECORDER_BUSY;
+       }
+
+       /* Add ecore timer to read audio data */
+       if (NULL != g_audio_timer) {
+               SLOG(LOG_DEBUG, TAG_STTD, "[Recorder] Timer is already created");
+               return STTD_ERROR_NONE;
+       }
+
+       g_audio_timer = ecore_timer_add(0, read_audio_func, NULL);
+       if (NULL == g_audio_timer) {
+               SLOG(LOG_WARN, TAG_STTD, "[Recorder WARNING] Fail to create timer of read_audio");
+               return STTD_ERROR_OPERATION_FAILED;
+       }
+
+       return STTD_ERROR_NONE;
+}
+
 int sttd_recorder_start(unsigned int uid, const char* appid)
 {
        if (STTD_RECORDER_STATE_RECORDING == g_recorder_state)
                return 0;
 
+       /* Check engine id is valid */
+       if (NULL == g_recorder) {
+               SLOG(LOG_WARN, TAG_STTD, "[Recorder WARNING] Engine id is not valid");
+               return STTD_ERROR_INVALID_PARAMETER;
+       }
+
        char* client_audio_id = NULL;
        int ret = sttd_client_get_audio_id(uid, &client_audio_id);
        if (STTD_ERROR_NONE != ret || NULL == client_audio_id) {
@@ -663,85 +708,55 @@ int sttd_recorder_start(unsigned int uid, const char* appid)
                return ret;
        }
 
+       bool is_valid_audio_id = false;
 #ifdef TV_FFV_MODE
-               if (0 == strncmp(client_audio_id, STTE_AUDIO_ID_FFV, strlen(client_audio_id))) {
-                       if (NULL != g_farfieldvoice_h) {
-                               SLOG(LOG_INFO, TAG_STTD, "[Recorder INFO] Register farfield voice audio callback");
-                               farfield_voice_register_audio_cb(g_farfieldvoice_h, _ffv_audio_function_cb, NULL);
-                       }
+       if (0 == strncmp(client_audio_id, STTE_AUDIO_ID_FFV, strlen(client_audio_id))) {
+               if (NULL != g_farfieldvoice_h) {
+                       SLOG(LOG_INFO, TAG_STTD, "[Recorder INFO] Register farfield voice audio callback");
+                       farfield_voice_register_audio_cb(g_farfieldvoice_h, _ffv_audio_function_cb, NULL);
                }
+
+               is_valid_audio_id = true;
+       }
 #endif
+
 #ifdef TV_BT_MODE
-               if (0 == strncmp(client_audio_id, STTE_AUDIO_ID_BLUETOOTH, strlen(client_audio_id))) {
-                       if (BT_ERROR_NONE != bt_hid_set_audio_data_receive_cb(_bt_hid_audio_data_receive_cb, NULL)) {
-                               SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail bt_hid_set_audio_data_receive_cb()");
-                               return STTD_ERROR_OPERATION_FAILED;
-                       }
+       if (0 == strncmp(client_audio_id, STTE_AUDIO_ID_BLUETOOTH, strlen(client_audio_id))) {
+               if (BT_ERROR_NONE != bt_hid_set_audio_data_receive_cb(_bt_hid_audio_data_receive_cb, NULL)) {
+                       SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail bt_hid_set_audio_data_receive_cb()");
+                       free(client_audio_id);
+                       return STTD_ERROR_OPERATION_FAILED;
                }
-#endif
 
-       free(client_audio_id);
-       client_audio_id = NULL;
-
-#ifndef TV_BT_MODE
-       ret = -1;
-       /* Check engine id is valid */
-       if (NULL == g_recorder) {
-               SLOG(LOG_WARN, TAG_STTD, "[Recorder WARNING] Engine id is not valid");
-               return STTD_ERROR_INVALID_PARAMETER;
-       }
+               if (true == is_tct_app(appid)) {
+                       start_recording_with_bt_rc_manually();
+               }
 
-       ret = audio_in_set_sound_stream_info(g_recorder->audio_h, g_stream_info_h);
-       if (AUDIO_IO_ERROR_NONE != ret) {
-               SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to set stream info");
+               is_valid_audio_id = true;
        }
+#endif
 
-       ret = audio_in_prepare(g_recorder->audio_h);
-       if (AUDIO_IO_ERROR_NONE != ret) {
-               SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to start audio : %d", ret);
-               return STTD_ERROR_RECORDER_BUSY;
-       }
+       if (0 == strncmp(client_audio_id, STTE_AUDIO_ID_NONE, strlen(client_audio_id))) {
+               if (STTD_ERROR_NONE != start_recording_with_audio_fw()) {
+                       SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to start recording with audio fw");
+                       free(client_audio_id);
+                       return STTD_ERROR_OPERATION_FAILED;
+               }
 
-       /* Add ecore timer to read audio data */
-       if (NULL != g_audio_timer) {
-               ecore_timer_del(g_audio_timer);
-               g_audio_timer = NULL;
+               is_valid_audio_id = true;
        }
 
-       g_audio_timer = ecore_timer_add(0, __read_audio_func, NULL);
-       if (NULL == g_audio_timer) {
-               SLOG(LOG_WARN, TAG_STTD, "[Recorder WARNING] Fail to create timer of read_audio");
+       if (false == is_valid_audio_id) {
+               SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to find behavior for audio id (%s)", client_audio_id);
+               free(client_audio_id);
                return STTD_ERROR_OPERATION_FAILED;
        }
-#else
-       if (true == __is_tct_app(appid)) {
-               int ret = -1;
-               int bt_retry = 0;
-               bool started = false;
-               while (5 > bt_retry) {
-                       ret = bt_hid_rc_start_sending_voice(NULL);
-                       if (BT_ERROR_NONE == ret) {
-                               SLOG(LOG_DEBUG, TAG_STTD, "[Recorder] Start bt audio");
-                               started = true;
-                               break;
-                       } else if (BT_ERROR_NOW_IN_PROGRESS == ret) {
-                               SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail bt_hid_rc_start_sending_voice()");
-                               usleep(50000);
-                               bt_retry++;
-                       } else {
-                               SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] bt_hid_rc_start_sending_voice(): ret(%d)", ret);
-                               break;
-                       }
-               }
-               if (false == started) {
-                       SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to start bt audio(%d)", ret);
-               }
-       }
-#endif
+
+       free(client_audio_id);
+       client_audio_id = NULL;
 
        g_recorder_state = STTD_RECORDER_STATE_RECORDING;
        g_recorder->uid = uid;
-
        g_buffer_count = 0;
 
 #ifdef BUF_SAVE_MODE
@@ -777,38 +792,10 @@ int sttd_recorder_start(unsigned int uid, const char* appid)
        return 0;
 }
 
-int sttd_recorder_stop()
+#ifdef TV_BT_MODE
+static void stop_recording_with_bt_rc_manually()
 {
-       if (STTD_RECORDER_STATE_READY == g_recorder_state)
-               return 0;
-
-       // critical section required because this function can be called from stt engine thread context
-       SLOG(LOG_WARN, TAG_STTD, "[Recorder WARNING] Enter critical section");
-       pthread_mutex_lock(&sttd_audio_in_handle_mutex);
-
-       sttd_engine_agent_set_audio_type(STTE_AUDIO_ID_NONE);
-
-       /* Check engine id is valid */
-       if (NULL == g_recorder) {
-               SLOG(LOG_WARN, TAG_STTD, "[Recorder WARNING] Engine id is not valid");
-               pthread_mutex_unlock(&sttd_audio_in_handle_mutex);
-               return STTD_ERROR_INVALID_PARAMETER;
-       }
-
-       g_recorder->uid = STT_INVALID_UID;
-
        int ret = -1;
-#ifndef TV_BT_MODE
-       if (NULL != g_audio_timer) {
-               ecore_timer_del(g_audio_timer);
-               g_audio_timer = NULL;
-       }
-
-       ret = audio_in_unprepare(g_recorder->audio_h);
-       if (AUDIO_IO_ERROR_NONE != ret) {
-               SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to unprepare audioin : %d", ret);
-       }
-#else
        int bt_retry = 0;
        bool stopped = false;
        while (5 > bt_retry) {
@@ -826,20 +813,80 @@ int sttd_recorder_stop()
                        break;
                }
        }
+
        if (false == stopped) {
                SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to stop bt audio(%d)", ret);
-//             return STTD_ERROR_OPERATION_FAILED;
        }
+}
 #endif
 
+static int stop_recording_with_audio_fw()
+{
+       if (NULL != g_audio_timer) {
+               ecore_timer_del(g_audio_timer);
+               g_audio_timer = NULL;
+       }
+
+       int ret = audio_in_unprepare(g_recorder->audio_h);
+       if (AUDIO_IO_ERROR_NONE != ret) {
+               SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to unprepare audioin : %d", ret);
+               return STTD_ERROR_OPERATION_FAILED;
+       }
+
+       return STTD_ERROR_NONE;
+}
+
+int sttd_recorder_stop()
+{
+       if (STTD_RECORDER_STATE_READY == g_recorder_state)
+               return 0;
+
+       // critical section required because this function can be called from stt engine thread context
+       SLOG(LOG_WARN, TAG_STTD, "[Recorder WARNING] Enter critical section");
+       pthread_mutex_lock(&sttd_audio_in_handle_mutex);
+
+       /* Check engine id is valid */
+       if (NULL == g_recorder) {
+               SLOG(LOG_WARN, TAG_STTD, "[Recorder WARNING] Engine id is not valid");
+               pthread_mutex_unlock(&sttd_audio_in_handle_mutex);
+               return STTD_ERROR_INVALID_PARAMETER;
+       }
+
+       char* client_audio_id = NULL;
+       int ret = sttd_client_get_audio_id(g_recorder->uid, &client_audio_id);
+       if (STTD_ERROR_NONE != ret || NULL == client_audio_id) {
+               SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to get audio id: %d", ret);
+               pthread_mutex_unlock(&sttd_audio_in_handle_mutex);
+               return ret;
+       }
+
+       sttd_engine_agent_set_audio_type(STTE_AUDIO_ID_NONE);
+       g_recorder->uid = STT_INVALID_UID;
+
 #ifdef TV_FFV_MODE
-       ret = farfield_voice_set_recognition_state(FARFIELD_VOICE_RECOGNITION_STOP);
-       if (0 != ret) {
-               SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to stop FFV, ret(%d)", ret);
+       if (0 == strncmp(client_audio_id, STTE_AUDIO_ID_FFV, strlen(client_audio_id))) {
+               ret = farfield_voice_set_recognition_state(FARFIELD_VOICE_RECOGNITION_STOP);
+               if (0 != ret) {
+                       SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to stop FFV, ret(%d)", ret);
+               }
+       }
+#endif
+
+#ifdef TV_BT_MODE
+       if (0 == strncmp(client_audio_id, STTE_AUDIO_ID_BLUETOOTH, strlen(client_audio_id))) {
+               stop_recording_with_bt_rc_manually();
        }
 #endif
 
+       if (0 == strncmp(client_audio_id, STTE_AUDIO_ID_NONE, strlen(client_audio_id))) {
+               if (STTD_ERROR_NONE != stop_recording_with_audio_fw()) {
+                       SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to stop recording with audio fw");
+               }
+       }
+
        g_recorder_state = STTD_RECORDER_STATE_READY;
+       free(client_audio_id);
+       client_audio_id = NULL;
 
 #ifdef BUF_SAVE_MODE
        fclose(g_pFile);