添加aiMediaService 2164/1 2164/head 2165/target/1
author孙春阳 <snickersun@163.com>
Thu, 28 Aug 2025 08:46:49 +0000 (16:46 +0800)
committer孙春阳 <snickersun@163.com>
Thu, 28 Aug 2025 08:46:49 +0000 (16:46 +0800)
ws测试采用sdk自带websockt
取消弃用的宏

code/sdk/zhihui/UI/producttest/src/testPing.cpp
code/sdk/zhihui/ai/include/ai_media.h [new file with mode: 0644]
code/sdk/zhihui/ai/media/CMakeLists.txt [new file with mode: 0644]
code/sdk/zhihui/ai/media/README.md [new file with mode: 0644]
code/sdk/zhihui/ai/media/ai_media_service.cpp [new file with mode: 0644]
code/sdk/zhihui/services/factorytest_service/factorytest_protocol.c
code/sdk/zhihui/utils/custom_utils.c
code/sdk/zhihui/websocket/test/ws_multi_test.c

index 2d818aa..9569ee9 100644 (file)
@@ -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 (file)
index 0000000..1a466fe
--- /dev/null
@@ -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 <stdint.h>
+
+#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 (file)
index 0000000..cd631ab
--- /dev/null
@@ -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 (file)
index 0000000..b2ed5e8
--- /dev/null
@@ -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<AudioStreamIn> 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<AudioStreamOut> 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 <vector>
+
+std::vector<uint8_t> 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 (file)
index 0000000..ac80cef
--- /dev/null
@@ -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 <climits>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string>
+#include <iostream>
+#include <unistd.h>
+#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<AudioStreamIn> 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<AudioStreamOut> 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<AIRecordInterruptListener> interruptListener =
+        std::make_shared<AIRecordInterruptListener>(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<AIPlaybackInterruptListener> interruptListener =
+        std::make_shared<AIPlaybackInterruptListener>(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
index 34e90ba..a2d6c95 100644 (file)
@@ -2069,33 +2069,33 @@ void factorytest_protocol_soft_test_decode(uint8_t submode,uint8_t testitem,uint
             {\r
                 //PING \r
                 uint8_t send_data = 0;\r
-#ifdef SUPPORT_TCPIP\r
-                char *str = (char *)malloc(len + 1);\r
-\r
-                if (str == NULL) \r
-                {\r
-                    PRINT("malloc failed\n");\r
-                    return;\r
-                }\r
-\r
-                // char *hostname = (char *)malloc(len + 1 + 8);\r
-                // if (hostname == NULL) \r
-                // {\r
-                //     PRINT("malloc failed\n");\r
-                //     free(str);\r
-                //     return;\r
-                // }\r
-\r
-                for (int i = 0; i < len; i++) \r
-                    str[i] = (char)data[i];\r
-                str[len] = '\0';\r
-\r
-                // sprintf(hostname,"www.%s.com",str);\r
-                // PRINT("hostname : %s\n",hostname);\r
-                send_data = OsShellPing(1,str);\r
-                // free(hostname);\r
-                free(str);\r
-#endif\r
+// #ifdef SUPPORT_TCPIP\r
+//                 char *str = (char *)malloc(len + 1);\r
+\r
+//                 if (str == NULL) \r
+//                 {\r
+//                     PRINT("malloc failed\n");\r
+//                     return;\r
+//                 }\r
+\r
+//                 // char *hostname = (char *)malloc(len + 1 + 8);\r
+//                 // if (hostname == NULL) \r
+//                 // {\r
+//                 //     PRINT("malloc failed\n");\r
+//                 //     free(str);\r
+//                 //     return;\r
+//                 // }\r
+\r
+//                 for (int i = 0; i < len; i++) \r
+//                     str[i] = (char)data[i];\r
+//                 str[len] = '\0';\r
+\r
+//                 // sprintf(hostname,"www.%s.com",str);\r
+//                 // PRINT("hostname : %s\n",hostname);\r
+//                 send_data = OsShellPing(1,str);\r
+//                 // free(hostname);\r
+//                 free(str);\r
+// #endif\r
                 factorytest_protocol_replymsg(BLE_TEST_CMD_MODE_SOFT_TEST,\r
                         BLE_TEST_CMD_SOFT_TEST_SUB_MODE_CAT1,\r
                         0x14,\r
index d5dafc7..ead43e5 100644 (file)
 #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"
index df26462..64bf6d3 100644 (file)
@@ -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