--- /dev/null
+/*
+ * Copyright (c) CompanyNameMagicTag. 2023-2023. All rights reserved.
+ * Description: 流式音频播放器实现
+ * Author: Media Software Group
+ * Create: 2023-12-01
+ */
+
+#include "audio_stream_player.h"
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <errno.h>
+
+// 包含音频管理相关头文件
+#include "audio_manager_c_wrapper.h"
+#include "media_log.h"
+#include "media_thread_adapt.h"
+#include "audio_base_type.h"
+#include "audio_manager.h"
+#include "audio_stream_out.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+// 线程/队列接口
+#include "thread_init.h"
+#include "errcode.h"
+#include "wearable_log.h"
+
+// 音频数据队列消息结构
+typedef struct
+{
+ uint8_t *data;
+ uint32_t size;
+ uint32_t timestamp;
+} AudioQueueMessage;
+
+// 音频流播放器上下文
+typedef struct
+{
+ AudioStreamConfig config; // 音频配置
+ AudioStreamState state; // 当前状态
+ AudioDataCallback dataCallback; // 数据回调
+ PlayStatusCallback statusCallback; // 状态回调
+ void *userData; // 用户数据
+
+ // 线程/队列
+ osMessageQueueId_t inputQueue; // 输入播放数据队列
+ uint32_t queueMsgCount; // 队列消息数量
+ MediaThreadIdHandle taskHandle; // 线程句柄
+ char threadName[32]; // 线程名称
+ bool isStopped; // 停止标志
+
+ // 统计信息
+ AudioStreamStats stats; // 统计信息
+
+ // 音频相关
+ void *audioStreamHandle; // 音频流句柄
+ float volume; // 音量
+ float speed; // 播放速度
+} AudioStreamPlayerContext;
+
+// 默认配置
+static const AudioStreamConfig DEFAULT_CONFIG = {
+ .sampleRate = 16000,
+ .channels = 1,
+ .bitsPerSample = 16,
+ .bufferSize = 2048,
+ .queueSize = 10};
+
+// 使用全局指针以配合uapi_create_osThread_custom
+static AudioStreamPlayerContext *g_audioStreamPlayerCtx = nullptr;
+
+// 队列创建函数(在线程创建时由系统调用)
+static void CreateAudioStreamQueue(void)
+{
+ if (g_audioStreamPlayerCtx != nullptr)
+ {
+ g_audioStreamPlayerCtx->inputQueue = osMessageQueueNew(g_audioStreamPlayerCtx->config.queueSize,
+ sizeof(AudioQueueMessage), nullptr);
+ if (g_audioStreamPlayerCtx->inputQueue == nullptr)
+ {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"Failed to create audio stream queue");
+ }
+ else
+ {
+ g_audioStreamPlayerCtx->queueMsgCount = 0;
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"Audio stream queue created successfully");
+ }
+ }
+}
+
+// 播放线程函数(与ai_media_service_ext风格保持一致)
+static void AudioStreamPlayThread(void *arg)
+{
+ (void)arg;
+ AudioStreamPlayerContext *ctx = g_audioStreamPlayerCtx;
+ if (ctx == nullptr)
+ {
+ MEDIA_ERR_LOG("AudioStreamPlayThread: context is null");
+ return;
+ }
+
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"AudioStreamPlayThread: started");
+
+ while (!ctx->isStopped)
+ {
+ if (ctx->inputQueue != nullptr)
+ {
+ AudioQueueMessage msg;
+ osStatus_t status = osMessageQueueGet(ctx->inputQueue, &msg, nullptr, 100); // 100ms超时
+ if (status == osOK)
+ {
+ if (msg.data != nullptr && msg.size > 0)
+ {
+ // 写入音频数据到输出流(重试逻辑)
+ WRITE_RETRY:
+ {
+ int32_t ret = AudioStreamOutStreamWrite(msg.data, msg.size);
+ if (ret != 0)
+ {
+ ctx->stats.retryCount++;
+ usleep(100000);
+ goto WRITE_RETRY;
+ }
+ ctx->stats.totalBytesPlayed += msg.size;
+ }
+
+ if (ctx->dataCallback != nullptr)
+ {
+ ctx->dataCallback(msg.data, msg.size, ctx->userData);
+ }
+ }
+
+ if (msg.data != nullptr)
+ {
+ free(msg.data);
+ }
+
+ if (ctx->queueMsgCount > 0)
+ {
+ ctx->queueMsgCount--;
+ }
+ ctx->stats.queueCurrentSize = ctx->queueMsgCount;
+ }
+ else if (status == osErrorTimeout)
+ {
+ continue;
+ }
+ else
+ {
+ MEDIA_ERR_LOG("AudioStreamPlayThread: queue get error=%d", status);
+ usleep(10000);
+ }
+ }
+ else
+ {
+ usleep(10000);
+ }
+ }
+
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"AudioStreamPlayThread: stopped");
+}
+
+// 创建音频流播放器
+int32_t AudioStreamPlayerCreate(const AudioStreamConfig *config, AudioStreamPlayerHandle *handle)
+{
+ if (handle == nullptr)
+ {
+ MEDIA_ERR_LOG("AudioStreamPlayerCreate: handle is null");
+ return -1;
+ }
+
+ // 分配上下文内存
+ AudioStreamPlayerContext *ctx = (AudioStreamPlayerContext *)malloc(sizeof(AudioStreamPlayerContext));
+ if (ctx == nullptr)
+ {
+ MEDIA_ERR_LOG("AudioStreamPlayerCreate: failed to allocate memory");
+ return -1;
+ }
+
+ // 初始化上下文
+ memset(ctx, 0, sizeof(AudioStreamPlayerContext));
+
+ // 设置配置
+ if (config != nullptr)
+ {
+ ctx->config = *config;
+ }
+ else
+ {
+ ctx->config = DEFAULT_CONFIG;
+ }
+
+ // 初始化状态
+ ctx->state = AUDIO_STREAM_STATE_IDLE;
+ ctx->volume = 1.0f;
+ ctx->speed = 1.0f;
+
+ // 队列/线程相关初值
+ ctx->inputQueue = nullptr;
+ ctx->queueMsgCount = 0;
+ ctx->taskHandle = nullptr;
+ ctx->threadName[0] = '\0';
+ ctx->isStopped = true;
+
+ *handle = (AudioStreamPlayerHandle)ctx;
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"AudioStreamPlayerCreate: success");
+ return 0;
+}
+
+// 初始化音频流播放器
+int32_t AudioStreamPlayerInit(AudioStreamPlayerHandle handle,
+ AudioDataCallback dataCallback,
+ PlayStatusCallback statusCallback,
+ void *userData)
+{
+ if (handle == nullptr)
+ {
+ MEDIA_ERR_LOG("AudioStreamPlayerInit: handle is null");
+ return -1;
+ }
+
+ AudioStreamPlayerContext *ctx = (AudioStreamPlayerContext *)handle;
+
+ // 设置回调函数
+ ctx->dataCallback = dataCallback;
+ ctx->statusCallback = statusCallback;
+ ctx->userData = userData;
+
+ // 初始化音频管理器
+ if (!AudioManagerInit())
+ {
+ MEDIA_ERR_LOG("AudioStreamPlayerInit: failed to init audio manager");
+ return -1;
+ }
+
+ // 获取音频会话ID
+ AudioSession sessionId = AudioManagerMakeSessionId();
+ if (sessionId == AUDIO_SESSION_ID_NONE)
+ {
+ MEDIA_ERR_LOG("AudioStreamPlayerInit: failed to get audio session ID");
+ return -1;
+ }
+
+ // 激活音频中断
+ if (AudioManagerActivateInterrupt(AUDIO_STREAM_VOICE_ASSISTANT, sessionId) == INTERRUPT_FAILED)
+ {
+ MEDIA_ERR_LOG("AudioStreamPlayerInit: failed to activate audio interrupt");
+ return -1;
+ }
+
+ // 配置音频流 - 参考ai_media_service_ext.cpp的实现
+ AudioRendererConfig renderConfig = {};
+ renderConfig.audioFormat = MP3; // 使用MP3格式,与原始代码一致
+ renderConfig.channelCount = ctx->config.channels;
+ renderConfig.linkDir = AUDIO_UP_LINK; // 上行链路,用于播放
+ renderConfig.sampleRate = ctx->config.sampleRate;
+ renderConfig.sessionID = sessionId;
+ renderConfig.streamType = AUDIO_STREAM_VOICE_ASSISTANT;
+
+ // 初始化音频输出流
+ int32_t ret = AudioStreamOutInit(renderConfig);
+ if (ret != 0)
+ {
+ MEDIA_ERR_LOG("AudioStreamPlayerInit: failed to init audio stream, ret=%d", ret);
+ AudioManagerDeactivateInterrupt();
+ return -1;
+ }
+
+ // 保存会话ID
+ ctx->audioStreamHandle = (void *)(uintptr_t)sessionId;
+
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"AudioStreamPlayerInit: success");
+ return 0;
+}
+
+// 开始播放
+int32_t AudioStreamPlayerStart(AudioStreamPlayerHandle handle)
+{
+ if (handle == nullptr)
+ {
+ MEDIA_ERR_LOG("AudioStreamPlayerStart: handle is null");
+ return -1;
+ }
+
+ AudioStreamPlayerContext *ctx = (AudioStreamPlayerContext *)handle;
+
+ if (ctx->state == AUDIO_STREAM_STATE_PLAYING)
+ {
+ MEDIA_WARNING_LOG("AudioStreamPlayerStart: already playing");
+ return 0;
+ }
+
+ // 启动音频流 - 参考ai_media_service_ext.cpp的实现
+ int32_t ret = AudioStreamOutPlay();
+ if (ret != 0)
+ {
+ MEDIA_ERR_LOG("AudioStreamPlayerStart: failed to start audio stream, ret=%d", ret);
+ return -1;
+ }
+
+ // 启动播放线程(uapi_create_osThread_custom)
+ ctx->isStopped = false;
+ ctx->state = AUDIO_STREAM_STATE_PLAYING;
+ g_audioStreamPlayerCtx = ctx;
+ app_task_definition_t task_cfg;
+ memset(&task_cfg, 0, sizeof(task_cfg));
+ task_cfg.create_queue_handle = CreateAudioStreamQueue;
+ task_cfg.attr.name = "AudioStreamPlayThread";
+ task_cfg.attr.priority = (osPriority_t)16;
+ task_cfg.attr.stack_size = 0x2000; // 8KB
+ task_cfg.func = AudioStreamPlayThread;
+ task_cfg.use_mem = USE_EXTEND_MEM;
+ extern errcode_t uapi_create_osThread_custom(app_task_definition_t * task_cfg);
+ errcode_t ret_errcode_t = uapi_create_osThread_custom(&task_cfg);
+ if (ret_errcode_t != ERRCODE_SUCC)
+ {
+ MEDIA_ERR_LOG("AudioStreamPlayerStart: failed to create thread: %d", ret_errcode_t);
+ ctx->isStopped = true;
+ ctx->state = AUDIO_STREAM_STATE_ERROR;
+ return -1;
+ }
+ ctx->taskHandle = (void *)task_cfg.task_handle;
+ strncpy(ctx->threadName, task_cfg.attr.name, sizeof(ctx->threadName) - 1);
+ ctx->threadName[sizeof(ctx->threadName) - 1] = '\0';
+
+ // 调用状态回调
+ if (ctx->statusCallback != nullptr)
+ {
+ ctx->statusCallback(AUDIO_STREAM_STATE_PLAYING, ctx->userData);
+ }
+
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"AudioStreamPlayerStart: success");
+ return 0;
+}
+
+// 暂停播放
+int32_t AudioStreamPlayerPause(AudioStreamPlayerHandle handle)
+{
+ if (handle == nullptr)
+ {
+ MEDIA_ERR_LOG("AudioStreamPlayerPause: handle is null");
+ return -1;
+ }
+
+ AudioStreamPlayerContext *ctx = (AudioStreamPlayerContext *)handle;
+
+ if (ctx->state != AUDIO_STREAM_STATE_PLAYING)
+ {
+ MEDIA_WARNING_LOG("AudioStreamPlayerPause: not playing");
+ return -1;
+ }
+
+ ctx->state = AUDIO_STREAM_STATE_PAUSED;
+
+ // 调用状态回调
+ if (ctx->statusCallback != nullptr)
+ {
+ ctx->statusCallback(AUDIO_STREAM_STATE_PAUSED, ctx->userData);
+ }
+
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"AudioStreamPlayerPause: success");
+ return 0;
+}
+
+// 恢复播放
+int32_t AudioStreamPlayerResume(AudioStreamPlayerHandle handle)
+{
+ if (handle == nullptr)
+ {
+ MEDIA_ERR_LOG("AudioStreamPlayerResume: handle is null");
+ return -1;
+ }
+
+ AudioStreamPlayerContext *ctx = (AudioStreamPlayerContext *)handle;
+
+ if (ctx->state != AUDIO_STREAM_STATE_PAUSED)
+ {
+ MEDIA_WARNING_LOG("AudioStreamPlayerResume: not paused");
+ return -1;
+ }
+
+ ctx->state = AUDIO_STREAM_STATE_PLAYING;
+
+ // 调用状态回调
+ if (ctx->statusCallback != nullptr)
+ {
+ ctx->statusCallback(AUDIO_STREAM_STATE_PLAYING, ctx->userData);
+ }
+
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"AudioStreamPlayerResume: success");
+ return 0;
+}
+
+// 停止播放
+int32_t AudioStreamPlayerStop(AudioStreamPlayerHandle handle)
+{
+ if (handle == nullptr)
+ {
+ MEDIA_ERR_LOG("AudioStreamPlayerStop: handle is null");
+ return -1;
+ }
+
+ AudioStreamPlayerContext *ctx = (AudioStreamPlayerContext *)handle;
+
+ if (ctx->state == AUDIO_STREAM_STATE_STOPPED)
+ {
+ MEDIA_WARNING_LOG("AudioStreamPlayerStop: already stopped");
+ return 0;
+ }
+
+ // 停止播放线程
+ ctx->isStopped = true;
+ ctx->state = AUDIO_STREAM_STATE_STOPPED;
+
+ // 等待线程结束(若支持)
+ if (ctx->taskHandle != nullptr)
+ {
+ osThreadId_t threadId = (osThreadId_t)ctx->taskHandle;
+ osThreadJoin(threadId);
+ ctx->taskHandle = nullptr;
+ }
+
+ // 停止音频流 - 参考ai_media_service_ext.cpp的实现
+ AudioStreamOutStop();
+
+ // 清理队列
+ if (ctx->inputQueue != nullptr)
+ {
+ AudioQueueMessage msg;
+ while (osMessageQueueGet(ctx->inputQueue, &msg, nullptr, 0) == osOK)
+ {
+ if (msg.data != nullptr)
+ {
+ free(msg.data);
+ }
+ }
+ osMessageQueueDelete(ctx->inputQueue);
+ ctx->inputQueue = nullptr;
+ ctx->queueMsgCount = 0;
+ ctx->stats.queueCurrentSize = 0;
+ }
+
+ // 停用音频中断
+ AudioManagerDeactivateInterrupt();
+
+ // 调用状态回调
+ if (ctx->statusCallback != nullptr)
+ {
+ ctx->statusCallback(AUDIO_STREAM_STATE_STOPPED, ctx->userData);
+ }
+
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"AudioStreamPlayerStop: success");
+ return 0;
+}
+
+// 写入音频数据到播放队列
+int32_t AudioStreamPlayerWrite(AudioStreamPlayerHandle handle, const uint8_t *data, uint32_t size)
+{
+ if (handle == nullptr || data == nullptr || size == 0)
+ {
+ MEDIA_ERR_LOG("AudioStreamPlayerWrite: invalid parameters");
+ return -1;
+ }
+
+ AudioStreamPlayerContext *ctx = (AudioStreamPlayerContext *)handle;
+
+ if (ctx->state != AUDIO_STREAM_STATE_PLAYING && ctx->state != AUDIO_STREAM_STATE_PAUSED)
+ {
+ MEDIA_ERR_LOG("AudioStreamPlayerWrite: player not in playing/paused state");
+ return -1;
+ }
+
+ // 分配内存并复制数据
+ uint8_t *dataCopy = (uint8_t *)malloc(size);
+ if (dataCopy == nullptr)
+ {
+ MEDIA_ERR_LOG("AudioStreamPlayerWrite: failed to allocate memory");
+ return -1;
+ }
+
+ memcpy(dataCopy, data, size);
+
+ // 发送到消息队列
+ if (ctx->inputQueue == nullptr)
+ {
+ MEDIA_ERR_LOG("AudioStreamPlayerWrite: queue not ready");
+ free(dataCopy);
+ return -1;
+ }
+
+ AudioQueueMessage msg;
+ msg.data = dataCopy;
+ msg.size = size;
+ msg.timestamp = (uint32_t)time(nullptr);
+
+ osStatus_t status = osMessageQueuePut(ctx->inputQueue, &msg, 0, 0);
+ if (status == osOK)
+ {
+ ctx->queueMsgCount++;
+ ctx->stats.queueCurrentSize = ctx->queueMsgCount;
+ MEDIA_DEBUG_LOG("AudioStreamPlayerWrite: queued %u bytes", size);
+ return 0;
+ }
+ else
+ {
+ MEDIA_WARNING_LOG("AudioStreamPlayerWrite: queue full or error=%d, dropping frame", status);
+ ctx->stats.droppedFrames++;
+ free(dataCopy);
+ return -1;
+ }
+}
+
+// 清空播放队列
+int32_t AudioStreamPlayerFlush(AudioStreamPlayerHandle handle)
+{
+ if (handle == nullptr)
+ {
+ MEDIA_ERR_LOG("AudioStreamPlayerFlush: handle is null");
+ return -1;
+ }
+
+ AudioStreamPlayerContext *ctx = (AudioStreamPlayerContext *)handle;
+ if (ctx->inputQueue != nullptr)
+ {
+ AudioQueueMessage msg;
+ while (osMessageQueueGet(ctx->inputQueue, &msg, nullptr, 0) == osOK)
+ {
+ if (msg.data != nullptr)
+ {
+ free(msg.data);
+ }
+ if (ctx->queueMsgCount > 0)
+ {
+ ctx->queueMsgCount--;
+ }
+ }
+ ctx->stats.queueCurrentSize = ctx->queueMsgCount;
+ }
+
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"AudioStreamPlayerFlush: success");
+ return 0;
+}
+
+// 获取播放器状态
+AudioStreamState AudioStreamPlayerGetState(AudioStreamPlayerHandle handle)
+{
+ if (handle == nullptr)
+ {
+ return AUDIO_STREAM_STATE_ERROR;
+ }
+
+ AudioStreamPlayerContext *ctx = (AudioStreamPlayerContext *)handle;
+ return ctx->state;
+}
+
+// 获取播放器统计信息
+int32_t AudioStreamPlayerGetStats(AudioStreamPlayerHandle handle, AudioStreamStats *stats)
+{
+ if (handle == nullptr || stats == nullptr)
+ {
+ MEDIA_ERR_LOG("AudioStreamPlayerGetStats: invalid parameters");
+ return -1;
+ }
+
+ AudioStreamPlayerContext *ctx = (AudioStreamPlayerContext *)handle;
+ *stats = ctx->stats;
+ return 0;
+}
+
+// 设置音量
+int32_t AudioStreamPlayerSetVolume(AudioStreamPlayerHandle handle, float volume)
+{
+ if (handle == nullptr || volume < 0.0f || volume > 1.0f)
+ {
+ MEDIA_ERR_LOG("AudioStreamPlayerSetVolume: invalid parameters");
+ return -1;
+ }
+
+ AudioStreamPlayerContext *ctx = (AudioStreamPlayerContext *)handle;
+ ctx->volume = volume;
+ // 设置音频流音量 - 使用AudioManagerSetVolume
+ AudioManagerSetVolume(AUDIO_STREAM_VOICE_ASSISTANT, (int32_t)(volume * 100));
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"AudioStreamPlayerSetVolume: set to %.2f", volume);
+ return 0;
+}
+
+// 销毁音频流播放器
+int32_t AudioStreamPlayerDestroy(AudioStreamPlayerHandle handle)
+{
+ if (handle == nullptr)
+ {
+ MEDIA_ERR_LOG("AudioStreamPlayerDestroy: handle is null");
+ return -1;
+ }
+
+ AudioStreamPlayerContext *ctx = (AudioStreamPlayerContext *)handle;
+
+ // 停止播放
+ AudioStreamPlayerStop(handle);
+
+ // 清空队列
+ AudioStreamPlayerFlush(handle);
+
+ // 销毁音频流 - 参考ai_media_service_ext.cpp的实现
+ AudioStreamOutDeinit();
+
+ // 队列已在Stop中销毁
+
+ // 释放上下文内存
+ free(ctx);
+
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"AudioStreamPlayerDestroy: success");
+ return 0;
+}
+
+
+/* 音频播放器全局句柄与初始化函数 */
+static AudioStreamPlayerHandle g_ln_audio_player = nullptr;
+
+/* 音频播放器状态回调函数 */
+static void ln_audio_player_status_cb(int32_t status, void *user)
+{
+ (void)user;
+ printf("[LN_AUDIO] status=%d\n", status);
+}
+
+/* 音频数据回调函数 */
+static void ln_audio_player_data_cb(const uint8_t *data, uint32_t size, void *user)
+{
+ (void)data;
+ (void)size;
+ (void)user;
+}
+
+/* 音频播放器初始化函数 */
+uint32_t ln_audio_player_init(void)
+{
+ if (g_ln_audio_player != nullptr) {
+ return ERRCODE_SUCC; /* 已初始化 */
+ }
+
+ AudioStreamConfig cfg;
+ cfg.sampleRate = 16000;
+ cfg.channels = 1;
+ cfg.bitsPerSample = 16;
+ cfg.bufferSize = 2048;
+ cfg.queueSize = 10;
+
+ if (AudioStreamPlayerCreate(&cfg, &g_ln_audio_player) != 0) {
+ printf("[LN_AUDIO] create failed\n");
+ g_ln_audio_player = nullptr;
+ return ERRCODE_FAIL;
+ }
+
+ if (AudioStreamPlayerInit(g_ln_audio_player, ln_audio_player_data_cb, ln_audio_player_status_cb, nullptr) != 0) {
+ printf("[LN_AUDIO] init failed\n");
+ AudioStreamPlayerDestroy(g_ln_audio_player);
+ g_ln_audio_player = nullptr;
+ return ERRCODE_FAIL;
+ }
+
+ if (AudioStreamPlayerStart(g_ln_audio_player) != 0) {
+ printf("[LN_AUDIO] start failed\n");
+ AudioStreamPlayerDestroy(g_ln_audio_player);
+ g_ln_audio_player = nullptr;
+ return ERRCODE_FAIL;
+ }
+
+ return ERRCODE_SUCC;
+}
+
+int32_t ln_audio_player_write(const uint8_t* data, uint32_t size)
+{
+ if (g_ln_audio_player == nullptr) {
+ if (ln_audio_player_init() != ERRCODE_SUCC) {
+ return -1;
+ }
+ }
+ return AudioStreamPlayerWrite(g_ln_audio_player, data, size);
+}
+
+#ifdef __cplusplus
+};
+#endif
\ No newline at end of file