From 9619fe847320c8ddb16cfb9846a70147aa40786d Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E5=AD=99=E6=98=A5=E9=98=B3?= Date: Thu, 28 Aug 2025 16:46:49 +0800 Subject: [PATCH] =?utf8?q?=E6=B7=BB=E5=8A=A0aiMediaService=20ws=E6=B5=8B?= =?utf8?q?=E8=AF=95=E9=87=87=E7=94=A8sdk=E8=87=AA=E5=B8=A6websockt=20?= =?utf8?q?=E5=8F=96=E6=B6=88=E5=BC=83=E7=94=A8=E7=9A=84=E5=AE=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .../zhihui/UI/producttest/src/testPing.cpp | 6 +- code/sdk/zhihui/ai/include/ai_media.h | 96 ++ code/sdk/zhihui/ai/media/CMakeLists.txt | 65 ++ code/sdk/zhihui/ai/media/README.md | 515 +++++++++++ code/sdk/zhihui/ai/media/ai_media_service.cpp | 835 ++++++++++++++++++ .../factorytest_protocol.c | 54 +- code/sdk/zhihui/utils/custom_utils.c | 8 +- .../sdk/zhihui/websocket/test/ws_multi_test.c | 2 +- 8 files changed, 1546 insertions(+), 35 deletions(-) create mode 100644 code/sdk/zhihui/ai/include/ai_media.h create mode 100644 code/sdk/zhihui/ai/media/CMakeLists.txt create mode 100644 code/sdk/zhihui/ai/media/README.md create mode 100644 code/sdk/zhihui/ai/media/ai_media_service.cpp diff --git a/code/sdk/zhihui/UI/producttest/src/testPing.cpp b/code/sdk/zhihui/UI/producttest/src/testPing.cpp index 2d818aa5a..9569ee9c4 100644 --- a/code/sdk/zhihui/UI/producttest/src/testPing.cpp +++ b/code/sdk/zhihui/UI/producttest/src/testPing.cpp @@ -12,9 +12,9 @@ #include "custom_runtime.h" #include "producttest/include/testView.h" -#ifdef SUPPORT_TCPIP -#include "api_shell.h" -#endif +// #ifdef SUPPORT_TCPIP +// #include "api_shell.h" +// #endif namespace OHOS { diff --git a/code/sdk/zhihui/ai/include/ai_media.h b/code/sdk/zhihui/ai/include/ai_media.h new file mode 100644 index 000000000..1a466fe55 --- /dev/null +++ b/code/sdk/zhihui/ai/include/ai_media.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) CompanyNameMagicTag. 2023-2023. All rights reserved. + * Description: voice call volte sample wrapper header + * Author: Media Software Group + * Create: 2023-07-06 + */ + +#ifndef AI_MEDIA_H +#define AI_MEDIA_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * @brief 初始化AI媒体服务 + * @return 0 on success, -1 on failure + */ +int32_t ai_media_service_init(void); + +/* + * @brief 反初始化AI媒体服务 + */ +void ai_media_service_deinit(void); +/* + * @brief 开始录音,默认采样率16000,默认通道数1,默认位深16,默认音频格式为PCM + * @param format 音频格式 "pcm","mp3","opus" + * @return 无 + */ +void ai_media_record_start(uint8_t* format); + +/* + * @brief 停止录音 + * @param 无 + * @return 无 + */ +void ai_media_record_stop(void); + +/* + * @brief 获取录音状态 + * @param 无 + * @return 录音状态 + */ +uint8_t ai_media_get_record_status(void); + +/* + * @brief 录音回调 + * @param 录音数据 + * @param 录音数据大小 + * @return 无 + */ +typedef void (*ai_media_record_callback)(uint8_t *data, uint32_t size); + +/* + * @brief 设置录音回调 + * @param 录音回调 + * @return 无 + */ +void ai_media_set_record_callback(ai_media_record_callback callback); + +/* + * @brief 开始播放 + * @param format 音频格式 "pcm","mp3","opus" + * @return 无 + */ +void ai_media_play_start(uint8_t* format); + +/* + * @brief 停止播放 + * @param 无 + * @return 无 + */ +void ai_media_play_stop(void); + +/* + * @brief 获取播放状态 + * @param 无 + * @return 播放状态 + */ +uint8_t ai_media_get_play_status(void); + +/* + * @brief 播放音频 + * @param 音频数据 + * @param 音频数据大小 + * @return 无 + */ +void ai_media_play_buffer(uint8_t *data, uint32_t size); + +#ifdef __cplusplus +}; +#endif + +#endif //AI_MEDIA_H diff --git a/code/sdk/zhihui/ai/media/CMakeLists.txt b/code/sdk/zhihui/ai/media/CMakeLists.txt new file mode 100644 index 000000000..cd631abee --- /dev/null +++ b/code/sdk/zhihui/ai/media/CMakeLists.txt @@ -0,0 +1,65 @@ +#=============================================================================== +# @brief cmake file +# Copyright (c) @CompanyNameMagicTag 2022-2022. All rights reserved. +#=============================================================================== + +set(COMPONENT_NAME "aiMediaService") + +set(PUBLIC_HEADER +) + + +set(PRIVATE_HEADER +${ROOT_DIR}/zhihui/ai/include +${ROOT_DIR}/middleware/services/media/foundation/audiomanager/interfaces/kits/audiomanager +${ROOT_DIR}/middleware/services/media/foundation/audiomanager/interfaces/kits/audiocommon +${ROOT_DIR}/middleware/services/media/foundation/audiomanager/frameworks/audiostream/include +${ROOT_DIR}/middleware/services/media/foundation/sample/wrapper +${ROOT_DIR}/middleware/services/media/foundation/utils/include +) + +set(AI_SOURCES +${CMAKE_CURRENT_SOURCE_DIR}/ai_media_service.cpp +) + +set(SOURCES + ${AI_SOURCES} +) + +set(COMPONENT_PUBLIC_CCFLAGS +) + +set(COMPONENT_CCFLAGS + -std=c++11 + -Wno-error + -Wno-unused-parameter + -fno-exceptions + -fno-unwind-tables + -fno-asynchronous-unwind-tables + -Wno-undef + -Wno-bitwise-op-parentheses + -Wno-shift-op-parentheses + -nostdlibinc + -nostdinc + -nostdlib + -Wno-c++11-narrowing + -Wno-error=unused-function +) + +set(WHOLE_LINK + true +) + +set(MAIN_COMPONENT + false +) + +set(PUBLIC_DEFINES +SUPPORT_AI_MEDIA_SERVICE +) + +set(PRIVATE_DEFINES +LOCAL_VOICE_CALL +) + +build_component() diff --git a/code/sdk/zhihui/ai/media/README.md b/code/sdk/zhihui/ai/media/README.md new file mode 100644 index 000000000..b2ed5e8b5 --- /dev/null +++ b/code/sdk/zhihui/ai/media/README.md @@ -0,0 +1,515 @@ +# AI Media Service - 音频录音和播放服务 + +## 概述 + +AI Media Service 是一个专为 AI 语音助手应用设计的音频录音和播放服务。它提供了完全分离的录音和播放功能,支持多种音频格式,具有线程安全、资源管理优化、完善的错误处理等特性。 + +## 核心功能 + +### 🎙️ 录音功能 +- **实时录音**: 支持连续音频录音 +- **回调机制**: 通过回调函数实时传递录音数据 +- **多格式支持**: PCM、MP3、OPUS 格式 +- **线程安全**: 独立录音线程,不阻塞主线程 + +### 🔊 播放功能 +- **缓冲播放**: 支持音频缓冲区播放 +- **流式播放**: 支持连续音频流播放 +- **格式兼容**: 与录音格式保持一致 +- **状态控制**: 完整的播放状态管理 + +### 🛡️ 系统特性 +- **音频焦点管理**: 完整的音频中断处理机制 +- **资源管理**: 自动资源分配和释放 +- **错误处理**: 完善的错误检查和恢复 +- **线程安全**: 多线程环境下的安全操作 + +## 架构设计 + +``` +AI Media Service +├── 录音子系统 (Recording Subsystem) +│ ├── AIRecordContext - 录音上下文 +│ ├── AIRecordInterruptListener - 录音中断监听器 +│ ├── RecordingThreadFunc - 录音线程函数 +│ └── 录音缓冲区管理 +├── 播放子系统 (Playback Subsystem) +│ ├── AIPlaybackContext - 播放上下文 +│ ├── AIPlaybackInterruptListener - 播放中断监听器 +│ └── 播放状态管理 +├── 音频管理 (Audio Management) +│ ├── AudioManager - 音频管理器 +│ ├── AudioInterrupt - 音频中断处理 +│ └── AudioSession - 音频会话管理 +└── 服务管理 (Service Management) + ├── 服务初始化/反初始化 + ├── 全局资源管理 + └── 线程安全保护 +``` + +## 数据结构 + +### 录音上下文 (AIRecordContext) +```cpp +typedef struct { + AudioSession sessionId; // 音频会话ID + AudioInterrupt interrupt; // 音频中断结构体 + bool isRecordingStopped; // 录音停止标志 + MediaMutexHandle mutex; // 互斥锁 + MediaThreadCondHandle cond; // 条件变量 + MediaThreadIdHandle recordThread; // 录音线程句柄 + std::shared_ptr streamIn; // 音频输入流 + uint8_t *recordBuffer; // 录音缓冲区 + uint32_t bufferSize; // 缓冲区大小 + AudioCodecFormat audioFormat; // 音频格式 + ai_media_record_callback recordCallback; // 录音回调函数 + bool isInitialized; // 初始化标志 +} AIRecordContext; +``` + +### 播放上下文 (AIPlaybackContext) +```cpp +typedef struct { + AudioSession sessionId; // 音频会话ID + AudioInterrupt interrupt; // 音频中断结构体 + bool isPlaybackStopped; // 播放停止标志 + MediaMutexHandle mutex; // 互斥锁 + MediaThreadCondHandle cond; // 条件变量 + MediaThreadIdHandle playThread; // 播放线程句柄 + std::shared_ptr streamOut; // 音频输出流 + AudioCodecFormat audioFormat; // 音频格式 + bool isInitialized; // 初始化标志 +} AIPlaybackContext; +``` + +## API 接口 + +### 服务管理接口 + +#### `ai_media_service_init()` +```cpp +int32_t ai_media_service_init(void); +``` +- **功能**: 初始化 AI 媒体服务 +- **返回值**: 0 成功,-1 失败 +- **说明**: 服务启动时自动调用,创建全局互斥锁 + +#### `ai_media_service_deinit()` +```cpp +void ai_media_service_deinit(void); +``` +- **功能**: 反初始化 AI 媒体服务 +- **说明**: 服务关闭时自动调用,清理所有资源 + +### 录音接口 + +#### `ai_media_record_start()` +```cpp +void ai_media_record_start(uint8_t* format); +``` +- **功能**: 开始音频录音 +- **参数**: + - `format`: 音频格式字符串 ("pcm", "mp3", "opus") +- **调用逻辑**: + 1. 检查录音状态,避免重复启动 + 2. 创建录音上下文和资源 + 3. 初始化 AudioManager 和音频会话 + 4. 创建音频中断监听器 + 5. 配置音频输入流 (16kHz, 单声道, 上行链路) + 6. 启动音频流和录音线程 + 7. 设置录音状态为活跃 + +#### `ai_media_record_stop()` +```cpp +void ai_media_record_stop(void); +``` +- **功能**: 停止音频录音 +- **调用逻辑**: + 1. 检查录音状态 + 2. 通知录音线程停止 + 3. 等待录音线程结束 + 4. 停止音频流并释放资源 + 5. 释放音频中断和会话 + 6. 清理录音上下文 + +#### `ai_media_get_record_status()` +```cpp +uint8_t ai_media_get_record_status(void); +``` +- **功能**: 获取录音状态 +- **返回值**: 0 停止,1 录音中 + +#### `ai_media_set_record_callback()` +```cpp +void ai_media_set_record_callback(ai_media_record_callback callback); +``` +- **功能**: 设置录音数据回调函数 +- **参数**: + - `callback`: 回调函数指针 +- **回调函数签名**: + ```cpp + typedef void (*ai_media_record_callback)(uint8_t *data, uint32_t size); + ``` + +### 播放接口 + +#### `ai_media_play_start()` +```cpp +void ai_media_play_start(uint8_t* format); +``` +- **功能**: 开始音频播放 +- **参数**: + - `format`: 音频格式字符串 ("pcm", "mp3", "opus") +- **调用逻辑**: + 1. 检查播放状态,避免重复启动 + 2. 创建播放上下文和资源 + 3. 初始化 AudioManager 和音频会话 + 4. 创建音频中断监听器 + 5. 配置音频输出流 (16kHz, 单声道, 下行链路) + 6. 启动音频流 + 7. 设置播放状态为活跃 + +#### `ai_media_play_stop()` +```cpp +void ai_media_play_stop(void); +``` +- **功能**: 停止音频播放 +- **调用逻辑**: + 1. 检查播放状态 + 2. 设置播放停止标志 + 3. 停止音频流并释放资源 + 4. 释放音频中断和会话 + 5. 清理播放上下文 + +#### `ai_media_get_play_status()` +```cpp +uint8_t ai_media_get_play_status(void); +``` +- **功能**: 获取播放状态 +- **返回值**: 0 停止,1 播放中 + +#### `ai_media_play_buffer()` +```cpp +void ai_media_play_buffer(uint8_t *data, uint32_t size); +``` +- **功能**: 播放音频缓冲区数据 +- **参数**: + - `data`: 音频数据缓冲区 + - `size`: 数据大小 +- **说明**: 需要先调用 `ai_media_play_start()` 启动播放 + +## 调用逻辑和时序 + +### 录音流程时序图 +``` +应用程序 AI Media Service AudioManager 录音线程 + | | | | + |-- ai_media_record_start() -->| | | + | |-- Initialize() ----->| | + | |-- MakeSessionId() --->| | + | |-- ActivateAudioInterrupt() -->| | + | |-- AudioStreamInInit() ------>| | + | |-- AudioStreamInStart() ----->| | + | |-- 创建录音线程 ------------->| | + | | | |-- 录音循环 --> + | | | | 获取音频数据 + | | | | 调用回调函数 + |-- 录音回调 <---------------------------| | | + | 处理音频数据 | | | | + | | | |<-- 继续录音 -- + |-- ai_media_record_stop() --->| | | + | |-- 通知线程停止 ------>| | + | |-- 等待线程结束 <------| | + | |-- AudioStreamInStop() ------>| + | |-- DeactivateAudioInterrupt() ->| + | |-- 清理资源 | | +``` + +### 播放流程时序图 +``` +应用程序 AI Media Service AudioManager + | | | + |-- ai_media_play_start() ---->| | + | |-- Initialize() ----->| + | |-- MakeSessionId() --->| + | |-- ActivateAudioInterrupt() -->| + | |-- AudioStreamOutInit() ----->| + | |-- AudioStreamOutPlay() ----->| + | | | + |-- ai_media_play_buffer() --->| | + | (音频数据) |-- AudioStreamOutStreamWrite() ->| + | | | + |-- ai_media_play_buffer() --->| | + | (更多数据) |-- AudioStreamOutStreamWrite() ->| + | | | + |-- ai_media_play_stop() ------>| | + | |-- AudioStreamOutStop() ------>| + | |-- DeactivateAudioInterrupt() ->| + | |-- 清理资源 | +``` + +## 使用示例 + +### 基本录音示例 +```cpp +#include "ai_media.h" + +// 录音数据回调函数 +void record_callback(uint8_t *data, uint32_t size) { + printf("收到录音数据: %u 字节\n", size); + // 处理录音数据 - 保存到文件、发送到网络等 + // save_to_file(data, size); +} + +int main() { + // 1. 设置录音回调 + ai_media_set_record_callback(record_callback); + + // 2. 开始录音 (PCM格式) + ai_media_record_start((uint8_t*)"pcm"); + + // 3. 检查录音状态 + if (ai_media_get_record_status() == 1) { + printf("录音已开始\n"); + } + + // 4. 录音10秒 + sleep(10); + + // 5. 停止录音 + ai_media_record_stop(); + printf("录音已停止\n"); + + return 0; +} +``` + +### 基本播放示例 +```cpp +#include "ai_media.h" + +int main() { + // 1. 开始播放 (PCM格式) + ai_media_play_start((uint8_t*)"pcm"); + + // 2. 检查播放状态 + if (ai_media_get_play_status() == 1) { + printf("播放已开始\n"); + } + + // 3. 播放音频数据 + uint8_t audio_buffer[1024]; + // ... 填充音频数据 ... + // load_audio_data(audio_buffer, 1024); + + ai_media_play_buffer(audio_buffer, 1024); + + // 4. 可以继续播放更多数据 + for (int i = 0; i < 100; i++) { + // load_next_chunk(audio_buffer, 1024); + ai_media_play_buffer(audio_buffer, 1024); + usleep(50000); // 50ms 延迟 + } + + // 5. 停止播放 + ai_media_play_stop(); + printf("播放已停止\n"); + + return 0; +} +``` + +### 录音播放循环示例 +```cpp +#include "ai_media.h" +#include + +std::vector recorded_data; + +// 录音回调 - 收集录音数据 +void collect_callback(uint8_t *data, uint32_t size) { + recorded_data.insert(recorded_data.end(), data, data + size); + printf("累计录音数据: %zu 字节\n", recorded_data.size()); +} + +int record_and_playback_demo() { + printf("=== 录音播放演示 ===\n"); + + // 1. 录音阶段 + printf("开始录音...\n"); + ai_media_set_record_callback(collect_callback); + ai_media_record_start((uint8_t*)"pcm"); + + sleep(5); // 录音5秒 + + ai_media_record_stop(); + printf("录音完成,共录制 %zu 字节\n", recorded_data.size()); + + // 2. 播放阶段 + printf("开始播放录音...\n"); + ai_media_play_start((uint8_t*)"pcm"); + + // 分块播放录音数据 + const size_t chunk_size = 1024; + size_t bytes_played = 0; + + while (bytes_played < recorded_data.size()) { + size_t current_chunk = std::min(chunk_size, recorded_data.size() - bytes_played); + ai_media_play_buffer(recorded_data.data() + bytes_played, current_chunk); + bytes_played += current_chunk; + + printf("已播放: %zu/%zu 字节\n", bytes_played, recorded_data.size()); + usleep(50000); // 50ms 延迟 + } + + ai_media_play_stop(); + printf("播放完成\n"); + + return 0; +} +``` + +## 配置参数 + +### 音频配置 +- **采样率**: 16000 Hz (固定) +- **通道数**: 1 (单声道,适合语音应用) +- **音频流类型**: AUDIO_STREAM_VOICE_ASSISTANT +- **录音缓冲区**: 2048 字节 (2KB) +- **链路方向**: + - 录音: AUDIO_UP_LINK (上行链路) + - 播放: AUDIO_DOWN_LINK (下行链路) + +### 支持的音频格式 +| 格式 | 描述 | 用途 | +|------|------|------| +| PCM | 脉冲编码调制,未压缩 | 高质量录音,实时处理 | +| MP3 | MPEG Audio Layer III | 压缩存储,网络传输 | +| OPUS | 开源音频编解码器 | 低延迟,高质量语音 | + +## 中断处理机制 + +### 录音中断处理 +```cpp +class AIRecordInterruptListener : public InterruptListener { + void OnInterrupt(int32_t type, int32_t hint) override { + // INTERRUPT_TYPE_BEGIN + INTERRUPT_HINT_PAUSE: 暂停录音 + // INTERRUPT_TYPE_END + INTERRUPT_HINT_RESUME: 恢复录音 + // INTERRUPT_TYPE_END + INTERRUPT_HINT_STOP: 停止录音 + } +}; +``` + +### 播放中断处理 +```cpp +class AIPlaybackInterruptListener : public InterruptListener { + void OnInterrupt(int32_t type, int32_t hint) override { + // INTERRUPT_TYPE_BEGIN + INTERRUPT_HINT_PAUSE: 暂停播放 + // INTERRUPT_TYPE_END + INTERRUPT_HINT_RESUME: 恢复播放 + // INTERRUPT_TYPE_END + INTERRUPT_HINT_STOP: 停止播放 + } +}; +``` + +## 错误处理 + +### 常见错误类型 +1. **初始化失败** + - AudioManager 初始化失败 + - 音频会话创建失败 + - 资源分配失败 + +2. **音频流错误** + - 音频流初始化失败 + - 音频流启动失败 + - 数据读写失败 + +3. **线程错误** + - 录音线程创建失败 + - 线程同步失败 + +### 错误处理策略 +- **完整的错误检查**: 每个关键操作都有错误检查 +- **资源清理**: 错误发生时自动清理已分配的资源 +- **状态恢复**: 错误后恢复到安全状态 +- **详细日志**: 提供详细的错误信息用于调试 + +## 性能优化 + +### 内存优化 +- 固定大小的录音缓冲区 (2KB) +- 智能指针管理音频流对象 +- 及时释放不需要的资源 + +### 线程优化 +- 独立的录音线程,避免阻塞主线程 +- 合理的线程属性设置 +- 最小化锁竞争 + +### 音频优化 +- 适中的缓冲区大小,平衡延迟和性能 +- 流式处理,减少内存占用 +- 高效的数据传输 + +## 调试和监控 + +### 日志系统 +```cpp +MEDIA_INFO_LOG("一般信息日志"); +MEDIA_WARNING_LOG("警告信息日志"); +MEDIA_ERR_LOG("错误信息日志"); +``` + +### 状态监控 +- 实时录音/播放状态查询 +- 资源使用情况监控 +- 线程状态监控 + +### 调试技巧 +1. 启用详细日志输出 +2. 监控音频数据流 +3. 检查资源分配和释放 +4. 验证线程同步 + +## 依赖项 + +### 系统依赖 +- OpenHarmony 音频系统 +- AudioManager 和 AudioStream 接口 +- 线程和同步原语支持 + +### 头文件依赖 +```cpp +#include "audio_base_type.h" // 音频基础类型 +#include "cpp/audio_manager.h" // C++ 音频管理器 +#include "cpp/audio_stream_in.h" // C++ 音频输入流 +#include "cpp/audio_stream_out.h" // C++ 音频输出流 +#include "media_thread_adapt.h" // 线程适配层 +``` + +## 总结 + +AI Media Service 提供了一个完整、高效、易用的音频录音和播放解决方案: + +### ✅ 核心优势 +- **功能完整**: 支持录音、播放、格式转换等完整功能 +- **架构清晰**: 录音和播放功能完全分离,职责明确 +- **线程安全**: 完善的多线程同步机制 +- **资源管理**: 自动化的资源分配和释放 +- **错误处理**: 完善的错误检查和恢复机制 +- **易于使用**: 简洁的 API 接口,清晰的调用逻辑 + +### 🎯 适用场景 +- AI 语音助手应用 +- 语音识别和合成 +- 音频录制和播放 +- 实时音频处理 +- 语音通话应用 + +### 🚀 扩展性 +- 支持新的音频格式 +- 可扩展的音频处理算法 +- 灵活的配置参数 +- 模块化的架构设计 + +这为 AI 应用提供了一个稳定、高效、功能完整的音频处理基础设施。 \ No newline at end of file diff --git a/code/sdk/zhihui/ai/media/ai_media_service.cpp b/code/sdk/zhihui/ai/media/ai_media_service.cpp new file mode 100644 index 000000000..ac80cef97 --- /dev/null +++ b/code/sdk/zhihui/ai/media/ai_media_service.cpp @@ -0,0 +1,835 @@ +/* + * Copyright (c) CompanyNameMagicTag. 2023-2023. All rights reserved. + * Description: AI Media Service - Refactored for separated recording and playback + * Author: Media Software Group + * Create: 2023-07-06 + * Modified: 2024-12-28 - Separated recording and playback functionality + */ + +#include "ai_media.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "securec.h" + +// Include audio base types first to avoid conflicts +#include "audio_base_type.h" +#include "cpp/audio_manager.h" +#include "cpp/audio_stream_in.h" +#include "cpp/audio_stream_out.h" + +#include "media_log.h" +#include "media_thread_adapt.h" +#include "audio_manager_c_wrapper.h" + +#ifdef __cplusplus +extern "C" { +#endif + +using namespace::Audio; + +#define MEDIA_CMD_LEN_MAX 128 +#define MEDIA_UNUSED(x) ((void)(x)) +#define ARRAY_SIZE(array) (sizeof((array)) / sizeof((array)[0])) + +const int32_t NUMBER_BASE = 10; +const int32_t CHANNEL_COUNT = 1; // Changed to 1 for AI applications +const int32_t SAMPLERATE_16000 = 16000; +const uint32_t RECORD_BUFFER_SIZE = 0x800; // 2KB buffer for recording + +/* ==================== AI Media Context Structures ==================== */ + +// Recording context structure +typedef struct { + AudioSession sessionId; + AudioInterrupt interrupt; + bool isRecordingStopped; + MediaMutexHandle mutex; + MediaThreadCondHandle cond; + MediaThreadIdHandle recordThread; + std::shared_ptr streamIn; + uint8_t *recordBuffer; + uint32_t bufferSize; + AudioCodecFormat audioFormat; + ai_media_record_callback recordCallback; + bool isInitialized; +} AIRecordContext; + +// Playback context structure +typedef struct { + AudioSession sessionId; + AudioInterrupt interrupt; + bool isPlaybackStopped; + MediaMutexHandle mutex; + MediaThreadCondHandle cond; + MediaThreadIdHandle playThread; + std::shared_ptr streamOut; + AudioCodecFormat audioFormat; + bool isInitialized; +} AIPlaybackContext; + +/* ==================== Interrupt Listener Classes ==================== */ + +class AIRecordInterruptListener : public InterruptListener { +public: + explicit AIRecordInterruptListener(AIRecordContext *ctx) : context(ctx) {} + ~AIRecordInterruptListener() override {} + + void OnInterrupt(int32_t type, int32_t hint) override + { + MEDIA_INFO_LOG("AI Record OnInterrupt, type:%d, hint:%d", type, hint); + + if (type == INTERRUPT_TYPE_BEGIN && hint == INTERRUPT_HINT_PAUSE) { + MEDIA_INFO_LOG("AI record pause signal"); + } + if (type == INTERRUPT_TYPE_END && hint == INTERRUPT_HINT_RESUME) { + MEDIA_INFO_LOG("AI record resume signal"); + } + if (type == INTERRUPT_TYPE_BEGIN && hint == INTERRUPT_HINT_STOP) { + MEDIA_INFO_LOG("AI record stop begin signal"); + } + if (type == INTERRUPT_TYPE_END && hint == INTERRUPT_HINT_STOP) { + MEDIA_INFO_LOG("AI record stop end signal"); + if (context != nullptr) { + context->isRecordingStopped = true; + } + } + } + +private: + AIRecordContext *context; +}; + +class AIPlaybackInterruptListener : public InterruptListener { +public: + explicit AIPlaybackInterruptListener(AIPlaybackContext *ctx) : context(ctx) {} + ~AIPlaybackInterruptListener() override {} + + void OnInterrupt(int32_t type, int32_t hint) override + { + MEDIA_INFO_LOG("AI Playback OnInterrupt, type:%d, hint:%d", type, hint); + + if (type == INTERRUPT_TYPE_BEGIN && hint == INTERRUPT_HINT_PAUSE) { + MEDIA_INFO_LOG("AI playback pause signal"); + } + if (type == INTERRUPT_TYPE_END && hint == INTERRUPT_HINT_RESUME) { + MEDIA_INFO_LOG("AI playback resume signal"); + } + if (type == INTERRUPT_TYPE_BEGIN && hint == INTERRUPT_HINT_STOP) { + MEDIA_INFO_LOG("AI playback stop begin signal"); + } + if (type == INTERRUPT_TYPE_END && hint == INTERRUPT_HINT_STOP) { + MEDIA_INFO_LOG("AI playback stop end signal"); + if (context != nullptr) { + context->isPlaybackStopped = true; + } + } + } + +private: + AIPlaybackContext *context; +}; + +/* ==================== Global Variables ==================== */ + +static MediaMutexHandle g_aiMediaMutex = nullptr; +static AIRecordContext *g_recordContext = nullptr; +static AIPlaybackContext *g_playbackContext = nullptr; +static Audio::AudioManager& g_amInstance = Audio::AudioManager::GetInstance(); + +// Recording status flags +static uint8_t g_recordStatus = 0; // 0: stopped, 1: recording +static uint8_t g_playStatus = 0; // 0: stopped, 1: playing + +/* ==================== Audio Format Helper Functions ==================== */ + +/** + * @brief Convert string format to AudioCodecFormat enum + * @param format Format string ("pcm", "mp3", "opus") + * @return AudioCodecFormat enum value + */ +static AudioCodecFormat GetAudioFormatFromString(const uint8_t* format) +{ + if (format == nullptr) { + return PCM; // Default to PCM + } + + if (strcmp((const char*)format, "mp3") == 0) { + return MP3; + } else if (strcmp((const char*)format, "opus") == 0) { + return OPUS; + } else { + return PCM; // Default to PCM for "pcm" or unknown formats + } +} + +/* ==================== Recording Implementation ==================== */ + +/** + * @brief Initialize recording resources + * @param context Recording context + * @return true on success, false on failure + */ +static bool InitRecordingResources(AIRecordContext *context) +{ + if (context == nullptr) { + MEDIA_ERR_LOG("Recording context is null"); + return false; + } + + // Create mutex and condition variable + context->mutex = MediaMutexCreate(nullptr); + if (context->mutex == nullptr) { + MEDIA_ERR_LOG("Failed to create recording mutex"); + return false; + } + + context->cond = MediaThreadCondCreate(); + if (context->cond == nullptr) { + MEDIA_ERR_LOG("Failed to create recording condition variable"); + MediaMutexDestroy(&context->mutex); + return false; + } + + // Allocate recording buffer + context->recordBuffer = (uint8_t*)malloc(RECORD_BUFFER_SIZE); + if (context->recordBuffer == nullptr) { + MEDIA_ERR_LOG("Failed to allocate recording buffer"); + MediaThreadCondDestroy(&context->cond); + MediaMutexDestroy(&context->mutex); + return false; + } + + context->bufferSize = RECORD_BUFFER_SIZE; + context->isInitialized = true; + return true; +} + +/** + * @brief Cleanup recording resources + * @param context Recording context + */ +static void CleanupRecordingResources(AIRecordContext *context) +{ + if (context == nullptr) { + return; + } + + if (context->streamIn != nullptr) { + context->streamIn->Stop(); + context->streamIn->Release(); + context->streamIn.reset(); + } + + if (context->recordBuffer != nullptr) { + free(context->recordBuffer); + context->recordBuffer = nullptr; + } + + if (context->cond != nullptr) { + MediaThreadCondDestroy(&context->cond); + context->cond = nullptr; + } + + if (context->mutex != nullptr) { + MediaMutexDestroy(&context->mutex); + context->mutex = nullptr; + } + + context->isInitialized = false; +} + +/** + * @brief Recording thread function + * @param priv Recording context pointer + * @return nullptr + */ +static void* RecordingThreadFunc(void* priv) +{ + AIRecordContext *context = (AIRecordContext*)priv; + if (context == nullptr) { + MEDIA_ERR_LOG("Recording context is null in thread"); + return nullptr; + } + + MEDIA_INFO_LOG("Recording thread started"); + + while (true) { + MediaMutexLock(context->mutex); + if (context->isRecordingStopped) { + MediaMutexUnLock(context->mutex); + break; + } + MediaMutexUnLock(context->mutex); + + // Obtain audio data from stream + uint32_t readSize = context->bufferSize; + int32_t ret = AudioStreamInObtainBuffer(context->recordBuffer, &readSize); + + if (ret == 0 && readSize > 0) { + // Call callback function to deliver recorded data + if (context->recordCallback != nullptr) { + context->recordCallback(context->recordBuffer, readSize); + } + } else { + // Sleep briefly if no data available + usleep(10000); // 10ms + } + } + + MEDIA_INFO_LOG("Recording thread stopped"); + return nullptr; +} + +/** + * @brief Start audio recording + * @param format Audio format string + */ +void ai_media_record_start(uint8_t* format) +{ + MEDIA_INFO_LOG("Starting AI media recording with format: %s", format ? (char*)format : "pcm"); + + MediaMutexLock(g_aiMediaMutex); + + // Check if already recording + if (g_recordContext != nullptr && g_recordStatus == 1) { + MEDIA_WARNING_LOG("Recording already in progress"); + MediaMutexUnLock(g_aiMediaMutex); + return; + } + + // Create recording context + if (g_recordContext == nullptr) { + g_recordContext = (AIRecordContext*)malloc(sizeof(AIRecordContext)); + if (g_recordContext == nullptr) { + MEDIA_ERR_LOG("Failed to allocate recording context"); + MediaMutexUnLock(g_aiMediaMutex); + return; + } + memset(g_recordContext, 0, sizeof(AIRecordContext)); + } + + // Initialize resources + if (!InitRecordingResources(g_recordContext)) { + MEDIA_ERR_LOG("Failed to initialize recording resources"); + free(g_recordContext); + g_recordContext = nullptr; + MediaMutexUnLock(g_aiMediaMutex); + return; + } + + // Set audio format + g_recordContext->audioFormat = GetAudioFormatFromString(format); + + // Request audio focus using C++ API + bool success = g_amInstance.Initialize(); + if (!success) { + MEDIA_ERR_LOG("AudioManager init failed"); + CleanupRecordingResources(g_recordContext); + free(g_recordContext); + g_recordContext = nullptr; + MediaMutexUnLock(g_aiMediaMutex); + return; + } + + AudioSession sessionId = g_amInstance.MakeSessionId(); + if (sessionId == AUDIO_SESSION_ID_NONE) { + MEDIA_ERR_LOG("Invalid audio session ID"); + CleanupRecordingResources(g_recordContext); + free(g_recordContext); + g_recordContext = nullptr; + MediaMutexUnLock(g_aiMediaMutex); + return; + } + + // Create interrupt listener and setup interrupt + std::shared_ptr interruptListener = + std::make_shared(g_recordContext); + if (interruptListener == nullptr || interruptListener.get() == nullptr) { + MEDIA_ERR_LOG("AI record interrupt listener is nullptr"); + CleanupRecordingResources(g_recordContext); + free(g_recordContext); + g_recordContext = nullptr; + MediaMutexUnLock(g_aiMediaMutex); + return; + } + + AudioInterrupt interrupt = { AUDIO_STREAM_VOICE_ASSISTANT, sessionId, interruptListener }; + if (g_amInstance.ActivateAudioInterrupt(interrupt) == INTERRUPT_FAILED) { + MEDIA_ERR_LOG("Failed to activate audio interrupt"); + CleanupRecordingResources(g_recordContext); + free(g_recordContext); + g_recordContext = nullptr; + MediaMutexUnLock(g_aiMediaMutex); + return; + } + + g_recordContext->interrupt = interrupt; + + g_recordContext->sessionId = sessionId; + + // Configure audio stream input + CapturerInputConfig captureConfig = {}; + captureConfig.audioFormat = g_recordContext->audioFormat; + captureConfig.channelCount = CHANNEL_COUNT; + captureConfig.linkDir = AUDIO_UP_LINK; + captureConfig.sampleRate = SAMPLERATE_16000; + captureConfig.sessionID = sessionId; + captureConfig.streamType = AUDIO_STREAM_VOICE_ASSISTANT; + + int32_t ret = AudioStreamInInit(captureConfig); + if (ret != 0) { + MEDIA_ERR_LOG("Audio stream in init failed"); + g_amInstance.DeactivateAudioInterrupt(g_recordContext->interrupt); + CleanupRecordingResources(g_recordContext); + free(g_recordContext); + g_recordContext = nullptr; + MediaMutexUnLock(g_aiMediaMutex); + return; + } + + ret = AudioStreamInStart(); + if (ret != 0) { + MEDIA_ERR_LOG("Audio stream in start failed"); + AudioStreamInDeinit(); + g_amInstance.DeactivateAudioInterrupt(g_recordContext->interrupt); + CleanupRecordingResources(g_recordContext); + free(g_recordContext); + g_recordContext = nullptr; + MediaMutexUnLock(g_aiMediaMutex); + return; + } + + // Start recording thread + g_recordContext->isRecordingStopped = false; + MediaThreadattr attr = { "AIRecordingThread", 0x2000, THREAD_SCHED_INVALID, 0, false }; + g_recordContext->recordThread = MediaThreadCreate(RecordingThreadFunc, g_recordContext, &attr); + + if (g_recordContext->recordThread == nullptr) { + MEDIA_ERR_LOG("Failed to create recording thread"); + AudioStreamInStop(); + AudioStreamInDeinit(); + g_amInstance.DeactivateAudioInterrupt(g_recordContext->interrupt); + CleanupRecordingResources(g_recordContext); + free(g_recordContext); + g_recordContext = nullptr; + MediaMutexUnLock(g_aiMediaMutex); + return; + } + + g_recordStatus = 1; // Set recording status + MediaMutexUnLock(g_aiMediaMutex); + + MEDIA_INFO_LOG("AI media recording started successfully"); +} + +/** + * @brief Stop audio recording + */ +void ai_media_record_stop(void) +{ + MEDIA_INFO_LOG("Stopping AI media recording"); + + MediaMutexLock(g_aiMediaMutex); + + if (g_recordContext == nullptr || g_recordStatus == 0) { + MEDIA_WARNING_LOG("Recording not in progress"); + MediaMutexUnLock(g_aiMediaMutex); + return; + } + + // Signal recording thread to stop + MediaMutexLock(g_recordContext->mutex); + g_recordContext->isRecordingStopped = true; + MediaThreadCondSignal(g_recordContext->cond); + MediaMutexUnLock(g_recordContext->mutex); + + // Wait for thread to finish + MediaThreadJoin(&g_recordContext->recordThread); + + // Stop audio stream + AudioStreamInStop(); + AudioStreamInDeinit(); + g_amInstance.DeactivateAudioInterrupt(g_recordContext->interrupt); + + // Cleanup resources + CleanupRecordingResources(g_recordContext); + free(g_recordContext); + g_recordContext = nullptr; + + g_recordStatus = 0; // Clear recording status + MediaMutexUnLock(g_aiMediaMutex); + + MEDIA_INFO_LOG("AI media recording stopped successfully"); +} + +/** + * @brief Get recording status + * @return Recording status (0: stopped, 1: recording) + */ +uint8_t ai_media_get_record_status(void) +{ + return g_recordStatus; +} + +/** + * @brief Set recording callback function + * @param callback Callback function for recorded data + */ +void ai_media_set_record_callback(ai_media_record_callback callback) +{ + MediaMutexLock(g_aiMediaMutex); + if (g_recordContext != nullptr) { + g_recordContext->recordCallback = callback; + } + MediaMutexUnLock(g_aiMediaMutex); + + MEDIA_INFO_LOG("Recording callback set"); +} + +/* ==================== Playback Implementation ==================== */ + +/** + * @brief Initialize playback resources + * @param context Playback context + * @return true on success, false on failure + */ +static bool InitPlaybackResources(AIPlaybackContext *context) +{ + if (context == nullptr) { + MEDIA_ERR_LOG("Playback context is null"); + return false; + } + + // Create mutex and condition variable + context->mutex = MediaMutexCreate(nullptr); + if (context->mutex == nullptr) { + MEDIA_ERR_LOG("Failed to create playback mutex"); + return false; + } + + context->cond = MediaThreadCondCreate(); + if (context->cond == nullptr) { + MEDIA_ERR_LOG("Failed to create playback condition variable"); + MediaMutexDestroy(&context->mutex); + return false; + } + + context->isInitialized = true; + return true; +} + +/** + * @brief Cleanup playback resources + * @param context Playback context + */ +static void CleanupPlaybackResources(AIPlaybackContext *context) +{ + if (context == nullptr) { + return; + } + + if (context->streamOut != nullptr) { + context->streamOut->Stop(); + context->streamOut->Release(); + context->streamOut.reset(); + } + + if (context->cond != nullptr) { + MediaThreadCondDestroy(&context->cond); + context->cond = nullptr; + } + + if (context->mutex != nullptr) { + MediaMutexDestroy(&context->mutex); + context->mutex = nullptr; + } + + context->isInitialized = false; +} + +/** + * @brief Start audio playback + * @param format Audio format string + */ +void ai_media_play_start(uint8_t* format) +{ + MEDIA_INFO_LOG("Starting AI media playback with format: %s", format ? (char*)format : "pcm"); + + MediaMutexLock(g_aiMediaMutex); + + // Check if already playing + if (g_playbackContext != nullptr && g_playStatus == 1) { + MEDIA_WARNING_LOG("Playback already in progress"); + MediaMutexUnLock(g_aiMediaMutex); + return; + } + + // Create playback context + if (g_playbackContext == nullptr) { + g_playbackContext = (AIPlaybackContext*)malloc(sizeof(AIPlaybackContext)); + if (g_playbackContext == nullptr) { + MEDIA_ERR_LOG("Failed to allocate playback context"); + MediaMutexUnLock(g_aiMediaMutex); + return; + } + memset(g_playbackContext, 0, sizeof(AIPlaybackContext)); + } + + // Initialize resources + if (!InitPlaybackResources(g_playbackContext)) { + MEDIA_ERR_LOG("Failed to initialize playback resources"); + free(g_playbackContext); + g_playbackContext = nullptr; + MediaMutexUnLock(g_aiMediaMutex); + return; + } + + // Set audio format + g_playbackContext->audioFormat = GetAudioFormatFromString(format); + + // Request audio focus using C++ API + bool success = g_amInstance.Initialize(); + if (!success) { + MEDIA_ERR_LOG("AudioManager init failed"); + CleanupPlaybackResources(g_playbackContext); + free(g_playbackContext); + g_playbackContext = nullptr; + MediaMutexUnLock(g_aiMediaMutex); + return; + } + + AudioSession sessionId = g_amInstance.MakeSessionId(); + if (sessionId == AUDIO_SESSION_ID_NONE) { + MEDIA_ERR_LOG("Invalid audio session ID"); + CleanupPlaybackResources(g_playbackContext); + free(g_playbackContext); + g_playbackContext = nullptr; + MediaMutexUnLock(g_aiMediaMutex); + return; + } + + // Create interrupt listener and setup interrupt + std::shared_ptr interruptListener = + std::make_shared(g_playbackContext); + if (interruptListener == nullptr || interruptListener.get() == nullptr) { + MEDIA_ERR_LOG("AI playback interrupt listener is nullptr"); + CleanupPlaybackResources(g_playbackContext); + free(g_playbackContext); + g_playbackContext = nullptr; + MediaMutexUnLock(g_aiMediaMutex); + return; + } + + AudioInterrupt interrupt = { AUDIO_STREAM_VOICE_ASSISTANT, sessionId, interruptListener }; + if (g_amInstance.ActivateAudioInterrupt(interrupt) == INTERRUPT_FAILED) { + MEDIA_ERR_LOG("Failed to activate audio interrupt"); + CleanupPlaybackResources(g_playbackContext); + free(g_playbackContext); + g_playbackContext = nullptr; + MediaMutexUnLock(g_aiMediaMutex); + return; + } + + g_playbackContext->interrupt = interrupt; + + g_playbackContext->sessionId = sessionId; + + // Configure audio stream output + AudioRendererConfig renderConfig = {}; + renderConfig.audioFormat = g_playbackContext->audioFormat; + renderConfig.channelCount = CHANNEL_COUNT; + renderConfig.linkDir = AUDIO_DOWN_LINK; + renderConfig.sampleRate = SAMPLERATE_16000; + renderConfig.sessionID = sessionId; + renderConfig.streamType = AUDIO_STREAM_VOICE_ASSISTANT; + + int32_t ret = AudioStreamOutInit(renderConfig); + if (ret != 0) { + MEDIA_ERR_LOG("Audio stream out init failed"); + g_amInstance.DeactivateAudioInterrupt(g_playbackContext->interrupt); + CleanupPlaybackResources(g_playbackContext); + free(g_playbackContext); + g_playbackContext = nullptr; + MediaMutexUnLock(g_aiMediaMutex); + return; + } + + ret = AudioStreamOutPlay(); + if (ret != 0) { + MEDIA_ERR_LOG("Audio stream out play failed"); + AudioStreamOutDeinit(); + g_amInstance.DeactivateAudioInterrupt(g_playbackContext->interrupt); + CleanupPlaybackResources(g_playbackContext); + free(g_playbackContext); + g_playbackContext = nullptr; + MediaMutexUnLock(g_aiMediaMutex); + return; + } + + g_playbackContext->isPlaybackStopped = false; + g_playStatus = 1; // Set playback status + MediaMutexUnLock(g_aiMediaMutex); + + MEDIA_INFO_LOG("AI media playback started successfully"); +} + +/** + * @brief Stop audio playback + */ +void ai_media_play_stop(void) +{ + MEDIA_INFO_LOG("Stopping AI media playback"); + + MediaMutexLock(g_aiMediaMutex); + + if (g_playbackContext == nullptr || g_playStatus == 0) { + MEDIA_WARNING_LOG("Playback not in progress"); + MediaMutexUnLock(g_aiMediaMutex); + return; + } + + // Signal playback to stop + MediaMutexLock(g_playbackContext->mutex); + g_playbackContext->isPlaybackStopped = true; + MediaThreadCondSignal(g_playbackContext->cond); + MediaMutexUnLock(g_playbackContext->mutex); + + // Stop audio stream + AudioStreamOutStop(); + AudioStreamOutDeinit(); + g_amInstance.DeactivateAudioInterrupt(g_playbackContext->interrupt); + + // Cleanup resources + CleanupPlaybackResources(g_playbackContext); + free(g_playbackContext); + g_playbackContext = nullptr; + + g_playStatus = 0; // Clear playback status + MediaMutexUnLock(g_aiMediaMutex); + + MEDIA_INFO_LOG("AI media playback stopped successfully"); +} + +/** + * @brief Get playback status + * @return Playback status (0: stopped, 1: playing) + */ +uint8_t ai_media_get_play_status(void) +{ + return g_playStatus; +} + +/** + * @brief Play audio buffer + * @param data Audio data buffer + * @param size Size of audio data + */ +void ai_media_play_buffer(uint8_t *data, uint32_t size) +{ + if (data == nullptr || size == 0) { + MEDIA_WARNING_LOG("Invalid audio data or size"); + return; + } + + MediaMutexLock(g_aiMediaMutex); + + if (g_playbackContext == nullptr || g_playStatus == 0) { + MEDIA_WARNING_LOG("Playback not started, call ai_media_play_start first"); + MediaMutexUnLock(g_aiMediaMutex); + return; + } + + // Check if playback is stopped + MediaMutexLock(g_playbackContext->mutex); + bool isStopped = g_playbackContext->isPlaybackStopped; + MediaMutexUnLock(g_playbackContext->mutex); + + if (isStopped) { + MEDIA_WARNING_LOG("Playback is stopped"); + MediaMutexUnLock(g_aiMediaMutex); + return; + } + + MediaMutexUnLock(g_aiMediaMutex); + + // Write audio data to stream + int32_t ret = AudioStreamOutStreamWrite(data, size); + if (ret != 0) { + MEDIA_ERR_LOG("Failed to write audio data to stream, ret=%d", ret); + } +} + +/* ==================== Module Initialization ==================== */ + +/** + * @brief Initialize AI media service + * @return 0 on success, -1 on failure + */ +int32_t ai_media_service_init(void) +{ + if (g_aiMediaMutex != nullptr) { + MEDIA_WARNING_LOG("AI media service already initialized"); + return 0; + } + + g_aiMediaMutex = MediaMutexCreate(nullptr); + if (g_aiMediaMutex == nullptr) { + MEDIA_ERR_LOG("Failed to create AI media mutex"); + return -1; + } + + MEDIA_INFO_LOG("AI media service initialized successfully"); + return 0; +} + +/** + * @brief Deinitialize AI media service + */ +void ai_media_service_deinit(void) +{ + // Stop recording if active + if (g_recordStatus == 1) { + ai_media_record_stop(); + } + + // Stop playback if active + if (g_playStatus == 1) { + ai_media_play_stop(); + } + + // Cleanup mutex + if (g_aiMediaMutex != nullptr) { + MediaMutexDestroy(&g_aiMediaMutex); + g_aiMediaMutex = nullptr; + } + + MEDIA_INFO_LOG("AI media service deinitialized"); +} + +/* ==================== Module Constructor/Destructor ==================== */ + +// Initialize the service when the module is loaded +__attribute__((constructor)) +static void ai_media_service_constructor(void) +{ + ai_media_service_init(); +} + +// Cleanup when the module is unloaded +__attribute__((destructor)) +static void ai_media_service_destructor(void) +{ + ai_media_service_deinit(); +} + +#ifdef __cplusplus +}; +#endif diff --git a/code/sdk/zhihui/services/factorytest_service/factorytest_protocol.c b/code/sdk/zhihui/services/factorytest_service/factorytest_protocol.c index 34e90ba41..a2d6c950d 100644 --- a/code/sdk/zhihui/services/factorytest_service/factorytest_protocol.c +++ b/code/sdk/zhihui/services/factorytest_service/factorytest_protocol.c @@ -2069,33 +2069,33 @@ void factorytest_protocol_soft_test_decode(uint8_t submode,uint8_t testitem,uint { //PING uint8_t send_data = 0; -#ifdef SUPPORT_TCPIP - char *str = (char *)malloc(len + 1); - - if (str == NULL) - { - PRINT("malloc failed\n"); - return; - } - - // char *hostname = (char *)malloc(len + 1 + 8); - // if (hostname == NULL) - // { - // PRINT("malloc failed\n"); - // free(str); - // return; - // } - - for (int i = 0; i < len; i++) - str[i] = (char)data[i]; - str[len] = '\0'; - - // sprintf(hostname,"www.%s.com",str); - // PRINT("hostname : %s\n",hostname); - send_data = OsShellPing(1,str); - // free(hostname); - free(str); -#endif +// #ifdef SUPPORT_TCPIP +// char *str = (char *)malloc(len + 1); + +// if (str == NULL) +// { +// PRINT("malloc failed\n"); +// return; +// } + +// // char *hostname = (char *)malloc(len + 1 + 8); +// // if (hostname == NULL) +// // { +// // PRINT("malloc failed\n"); +// // free(str); +// // return; +// // } + +// for (int i = 0; i < len; i++) +// str[i] = (char)data[i]; +// str[len] = '\0'; + +// // sprintf(hostname,"www.%s.com",str); +// // PRINT("hostname : %s\n",hostname); +// send_data = OsShellPing(1,str); +// // free(hostname); +// free(str); +// #endif factorytest_protocol_replymsg(BLE_TEST_CMD_MODE_SOFT_TEST, BLE_TEST_CMD_SOFT_TEST_SUB_MODE_CAT1, 0x14, diff --git a/code/sdk/zhihui/utils/custom_utils.c b/code/sdk/zhihui/utils/custom_utils.c index d5dafc7b6..ead43e5f0 100644 --- a/code/sdk/zhihui/utils/custom_utils.c +++ b/code/sdk/zhihui/utils/custom_utils.c @@ -31,10 +31,10 @@ #include "upg_porting.h" #include "soc_lcd_api.h" #include "flash.h" -#ifdef SUPPORT_TCPIP -#include "lwip/tcpip.h" -#include "lwip/sys.h" -#endif +// #ifdef SUPPORT_TCPIP +// #include "lwip/tcpip.h" +// #include "lwip/sys.h" +// #endif #include "system/include/SystemLogModelC.h" #ifdef FD230 #include "soundandvibration/include/SoundAndVibrationVolumeSettingC.h" diff --git a/code/sdk/zhihui/websocket/test/ws_multi_test.c b/code/sdk/zhihui/websocket/test/ws_multi_test.c index df26462db..64bf6d34a 100644 --- a/code/sdk/zhihui/websocket/test/ws_multi_test.c +++ b/code/sdk/zhihui/websocket/test/ws_multi_test.c @@ -17,7 +17,7 @@ /* WebSocket 相关头文件 */ // 宏定义:USE_ZHIHUI_WEBSOCKET = 1 使用新的zhihui接口,= 0 使用海思原有接口 -#define USE_ZHIHUI_WEBSOCKET 1 +#define USE_ZHIHUI_WEBSOCKET 0 #ifndef USE_ZHIHUI_WEBSOCKET #define USE_ZHIHUI_WEBSOCKET 0 // 默认使用原有接口 #endif -- 2.17.1