From c64e7d07855c612b51f14db96fda515f8b0bdfb7 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E8=83=A1=E4=BC=A0=E5=86=9B?= <1224667075@qq.com> Date: Fri, 31 Oct 2025 11:56:57 +0000 Subject: [PATCH] Merge #2647 into sdk650pathc0423 from refs/changes/2647/head MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Code review from 胡传军 * refs/changes/2647/head: (4 commits squashed) - 修改活动界面UI显示问题 - Merge branch 'sdk650pathc0423' of https://codeup.aliyun.com/64191456b9581d62e8f81ac0/FD230 into sdk650pathc0423 - VAD修改 - 优化部分雷鸟代码 Signed-off-by: aliyun8003852482 <1224667075@qq.com> Merged-by: 罗正 <1732036298@qq.com> CR-link: https://codeup.aliyun.com/64191456b9581d62e8f81ac0/FD230/change/2647 --- .../zhihui/ai/media/ai_media_service_ext.cpp | 18 +++++++++++++++ code/sdk/zhihui/imsl/src/vad_server.c | 2 +- .../zhihui/leiniao/imsl_ln/ln_api_websocket.c | 23 ++++++++----------- .../zhihui/websocket/os_ws/haisi_websocket.c | 14 ++++++++--- 4 files changed, 40 insertions(+), 17 deletions(-) diff --git a/code/sdk/zhihui/ai/media/ai_media_service_ext.cpp b/code/sdk/zhihui/ai/media/ai_media_service_ext.cpp index 0901102fb..0be86ce83 100644 --- a/code/sdk/zhihui/ai/media/ai_media_service_ext.cpp +++ b/code/sdk/zhihui/ai/media/ai_media_service_ext.cpp @@ -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(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; } diff --git a/code/sdk/zhihui/imsl/src/vad_server.c b/code/sdk/zhihui/imsl/src/vad_server.c index a93835a7d..828ff1113 100644 --- a/code/sdk/zhihui/imsl/src/vad_server.c +++ b/code/sdk/zhihui/imsl/src/vad_server.c @@ -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) */ diff --git a/code/sdk/zhihui/leiniao/imsl_ln/ln_api_websocket.c b/code/sdk/zhihui/leiniao/imsl_ln/ln_api_websocket.c index 4f54746c5..41a7673b6 100644 --- a/code/sdk/zhihui/leiniao/imsl_ln/ln_api_websocket.c +++ b/code/sdk/zhihui/leiniao/imsl_ln/ln_api_websocket.c @@ -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); diff --git a/code/sdk/zhihui/websocket/os_ws/haisi_websocket.c b/code/sdk/zhihui/websocket/os_ws/haisi_websocket.c index 17baf7584..929852725 100644 --- a/code/sdk/zhihui/websocket/os_ws/haisi_websocket.c +++ b/code/sdk/zhihui/websocket/os_ws/haisi_websocket.c @@ -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; } -- 2.17.1