Merge #2647 into sdk650pathc0423 from refs/changes/2647/head 2652/target/1
author胡传军 <1224667075@qq.com>
Fri, 31 Oct 2025 11:56:57 +0000 (11:56 +0000)
committer罗正 <1732036298@qq.com>
Fri, 31 Oct 2025 11:56:57 +0000 (11:56 +0000)
Code review from 胡传军

* refs/changes/2647/head: (4 commits squashed)

  - 修改活动界面UI显示问题

  - Merge branch &#39;sdk650pathc0423&#39; of https://codeup.aliyun.com/64191456b9581d62e8f81ac0/FD230 into sdk650pathc0423

  - VAD修改

  - 优化部分雷鸟代码

Signed-off-by: aliyun8003852482 <1224667075@qq.com>
Merged-by: 罗正 <1732036298@qq.com>
link: https://codeup.aliyun.com/64191456b9581d62e8f81ac0/FD230/change/2647
code/sdk/zhihui/ai/media/ai_media_service_ext.cpp
code/sdk/zhihui/imsl/src/vad_server.c
code/sdk/zhihui/leiniao/imsl_ln/ln_api_websocket.c
code/sdk/zhihui/websocket/os_ws/haisi_websocket.c

index 0901102..0be86ce 100644 (file)
@@ -371,6 +371,7 @@ static int32_t AudioCapturerOggHeaderInit(CaptureOggContext *oggCtx, uint32_t ch
     
     if (memcpy_s(oggCtx->idHeader, HEADER_STRLEN, "OpusHead", HEADER_STRLEN) != 0) {
         MEDIA_ERR_LOG("memcpy failed!");
+        MediaMemFree((void **)&oggCtx->idHeader);
         return -1;
     }  
     oggCtx->idHeader[0x8] = 0x01;
@@ -386,11 +387,14 @@ static int32_t AudioCapturerOggHeaderInit(CaptureOggContext *oggCtx, uint32_t ch
     oggCtx->commentHeader = static_cast<unsigned char*>(MediaMemCalloc(OPUS_COMMENT_HEADER_LEN));
     if (oggCtx->commentHeader == nullptr) {
         MEDIA_ERR_LOG("malloc failed!");
+        MediaMemFree((void **)&oggCtx->idHeader);
         return -1;
     }
     
     if (memcpy_s(oggCtx->commentHeader, HEADER_STRLEN, "OpusTags", HEADER_STRLEN) != 0) {
         MEDIA_ERR_LOG("Opus idHeader memcpy failed!");
+        MediaMemFree((void **)&oggCtx->idHeader);
+        MediaMemFree((void **)&oggCtx->commentHeader);
         return -1;
     }
     const char *vendor = "libogg-1.3.5";
@@ -402,6 +406,8 @@ static int32_t AudioCapturerOggHeaderInit(CaptureOggContext *oggCtx, uint32_t ch
 
     if (memcpy_s(oggCtx->commentHeader + OPUS_OPUSTAGS_LEN, vendorLen, vendor, vendorLen) != 0) {
         MEDIA_ERR_LOG("Opus commentHeader memcpy failed!");
+        MediaMemFree((void **)&oggCtx->idHeader);
+        MediaMemFree((void **)&oggCtx->commentHeader);
         return -1;
     }
     return 0;
@@ -419,6 +425,7 @@ static int32_t AudioCapturerOggCtxInit(CaptureOggContext *oggCtx, uint32_t chann
     oggCtx->page = (ogg_page *)MediaMemCalloc(sizeof(ogg_page));
     if (oggCtx->page == nullptr) {
         MEDIA_ERR_LOG("malloc failed!");
+        MediaMemFree((void **)&oggCtx->packet);
         return -1;
     }
     
@@ -431,11 +438,16 @@ static int32_t AudioCapturerOggCtxInit(CaptureOggContext *oggCtx, uint32_t chann
     
     if (ogg_stream_init(&oggCtx->oggStream, oggCtx->serialno) != 0) {
         MEDIA_ERR_LOG("ogg stream init failed");
+        MediaMemFree((void **)&oggCtx->packet);
+        MediaMemFree((void **)&oggCtx->page);
         return -1;
     }
     
     if (AudioCapturerOggHeaderInit(oggCtx, channelCount, sampleRate) != 0) {
         MEDIA_ERR_LOG("Header init failed!");
+        ogg_stream_clear(&oggCtx->oggStream);
+        MediaMemFree((void **)&oggCtx->packet);
+        MediaMemFree((void **)&oggCtx->page);
         return -1;
     }
     
@@ -1084,6 +1096,10 @@ static int32_t RunAIVoice(AIVoiceContext *context)
                                 // 如果队列写入失败,释放内存
                                 free(cachedMsg.data);
                             }
+                        } else if (cachedMsg.data != nullptr) {
+                            // 防御性处理:如果data不为null但size为0,也应该释放
+                            MEDIA_ERR_LOG("Invalid cached message: data not null but size is 0 or invalid");
+                            free(cachedMsg.data);
                         }
                     } else {
                         MEDIA_ERR_LOG("Failed to read from file cache");
@@ -1252,6 +1268,8 @@ static void AIVoiceThread(void *priv)
     int32_t ret = RunAIVoice(context);
     if (ret != 0) {
         MEDIA_ERR_LOG("run AI voice failed");
+        // 清理已分配的资源(RunAIVoice中的InitAIVoiceResources可能已分配资源)
+        DeinitAIVoiceResources(context);
         (void)ReleaseAudioFocus();
         return;
     }
index a93835a..828ff11 100644 (file)
@@ -382,7 +382,7 @@ errcode_t vad_server_init(vad_status_callback_t callback)
     struct VadConfig vad_config = {
         .vad_log_level = 1,                   /* INFO 日志 */
         .sil_threshold = 63,                  /* 静音阈值 */
-        .energy_threshold = 10000,            /* 能量阈值 */
+        .energy_threshold = 50000,            /* 能量阈值 */
         .min_speech_length = 240,             /* 最短语音长度 (ms) */
         .silence_detect_length = 300,         /* 静音检测长度 (ms) */
         .rule1_min_tailing_silence = 480,     /* 规则1静音时间 (ms) */
index 4f54746..41a7673 100644 (file)
@@ -566,20 +566,20 @@ int ln_ws_send_audio_data(const uint8_t *audio_data, uint32_t audio_size, bool f
         audio_base64[0] = '\0';
     } else {
         // 正常音频数据,进行Base64编码
-        size_t base64_size =audio_size*2; //((audio_size + 2) / 3) * 4 + 1;
+        size_t base64_size = audio_size * 2; //((audio_size + 2) / 3) * 4 + 1;
         audio_base64 = (char*)malloc(base64_size);
         if (!audio_base64) {
             LN_WS_ERROR("Failed to allocate memory for base64 encoding\n");
-        return -1;
-    }
-    
+            return -1;
+        }
+        
         size_t output_len = 0;
         int ret_encode = mbedtls_base64_encode((unsigned char*)audio_base64, base64_size - 1, &output_len, 
                                               audio_data, audio_size);
         if (ret_encode != 0) {
             LN_WS_DEBUG("Base64 encoding failed: %d\n", ret_encode);
             free(audio_base64);
-        return -1;
+            return -1;
         }
         audio_base64[output_len] = '\0';
     }
@@ -1069,9 +1069,9 @@ void vad_status_callback_ln_ws(int status)
             LN_WS_INFO("VAD cooldown active, ignoring start request\n");
     return;
     }
-        #ifdef VAD_TEST
+        // #ifdef VAD_TEST
         ln_ws_start_audio_chat(LN_AUDIO_CHAT_VOICE_CHAT_REQUEST);
-        #endif
+        // #endif
     }
     else
     if (status==2)
@@ -3163,12 +3163,9 @@ static int ln_ws_send_cached_audio_data(void)
             break;
         }
         
-        // 判断是否是最后一块
-        bool is_last = (remaining <= chunk_size);
-        
-        // 发送数据
-        LN_WS_DEBUG("Sending chunk: size=%u, remaining=%u, is_last=%d\n", 
-                   chunk_size, remaining - chunk_size, is_last);
+        // 发送数据(所有块都标记为finished=false,因为这是缓存的历史数据)
+        LN_WS_DEBUG("Sending chunk: size=%u, remaining=%u\n", 
+                   chunk_size, remaining - chunk_size);
         
         ret = ln_ws_send_audio_data(send_buffer, chunk_size, false);
         
index 17baf75..9298527 100644 (file)
@@ -542,8 +542,8 @@ static void uapi_ws_main_thread(void *arg)
         ws_msg_info_t msg;
         while (osMessageQueueGet(g_ws_msg_queue, &msg, NULL, 0) == osOK) {
             // 原始消息数据不需要额外释放,因为存储在栈上
-            HAISI_WS_DEBUG("Clearing queued message: %s\n", msg.raw_data);
-            ws_msg_free(&msg);
+                HAISI_WS_DEBUG("Clearing queued message: %s\n", msg.raw_data);
+                ws_msg_free(&msg);
             
         }
         osMessageQueueDelete(g_ws_msg_queue);
@@ -746,8 +746,16 @@ int uapi_ws_stop(void)
     }
     g_ws_connected = WS_STATE_DISCONNECTED;
     
-    // 删除消息队列
+    // 删除消息队列(先清理所有消息)
     if (g_ws_msg_queue != NULL) {
+        // 队列中存储的是 ws_msg_info_t* 指针,需要先清理所有消息
+        ws_msg_info_t *msg;
+        while (osMessageQueueGet(g_ws_msg_queue, &msg, NULL, 0) == osOK) {
+            if (msg != NULL) {
+                HAISI_WS_DEBUG("Clearing queued message before stop\n");
+                ws_msg_free(msg);  // 释放动态分配的消息结构体和raw_data
+            }
+        }
         osMessageQueueDelete(g_ws_msg_queue);
         g_ws_msg_queue = NULL;
     }