ESP-ADF esp_dispatcher组件之audio_service子模块资源管理函数详解
目录
- ESP-ADF esp_dispatcher组件之audio_service子模块资源管理函数详解
- 内部数据结构
- 结构体关系图
- 资源管理函数分析
- audio_service_create
- audio_service_destroy
ESP-ADF esp_dispatcher组件之audio_service子模块资源管理函数详解
版本信息: v2.7-65-gcf908721
本章节分析的源码位于
/components/esp_dispatcher/audio_service.c
文件
内部数据结构
audio_service子模块内部定义了关键的结构体,用于实现音频服务管理:
/*** @brief 音频服务实现结构体*/
typedef struct audio_service_impl {service_ctrl service_start; // 服务启动函数service_ctrl service_stop; // 服务停止函数service_ctrl service_connect; // 服务连接函数service_ctrl service_disconnect; // 服务断开连接函数service_ctrl service_destroy; // 服务销毁函数service_callback callback_func; // 回调函数void *user_cb_ctx; // 用户回调上下文char *service_name; // 服务名称TaskHandle_t task_handle; // 任务句柄void *user_data; // 用户数据
} audio_service_impl_t;
与此相关的公开结构体和类型定义包括:
// 音频服务状态
typedef enum {SERVICE_STATE_UNKNOWN, // 未知状态SERVICE_STATE_IDLE, // 空闲状态SERVICE_STATE_CONNECTING, // 连接中状态SERVICE_STATE_CONNECTED, // 已连接状态SERVICE_STATE_RUNNING, // 运行状态SERVICE_STATE_STOPPED, // 停止状态
} service_state_t;// 音频服务事件信息
typedef struct {int type; // 事件类型void *source; // 事件源void *data; // 事件数据int len; // 数据长度
} service_event_t;// 服务控制函数类型
typedef esp_err_t (*service_ctrl)(audio_service_handle_t handle);// 服务回调函数类型
typedef esp_err_t (*service_callback)(audio_service_handle_t handle, service_event_t *evt, void *ctx);// 音频服务配置
typedef struct {int task_stack; // >0 服务任务栈大小; =0 不创建任务int task_prio; // 服务任务优先级(基于FreeRTOS优先级)int task_core; // 服务任务运行的核心(0或1)TaskFunction_t task_func; // 服务任务函数service_ctrl service_start; // 启动函数service_ctrl service_stop; // 停止函数service_ctrl service_connect; // 连接函数service_ctrl service_disconnect; // 断开连接函数service_ctrl service_destroy; // 销毁函数const char *service_name; // 音频服务名称void *user_data; // 用户数据
} audio_service_config_t;
结构体关系图
下面的图表展示了这些结构体之间的关系:
这个图表展示了音频服务的核心数据结构及其关系:
audio_service_config_t
是创建音频服务时的配置结构体,包含任务参数和各种回调函数audio_service_impl_t
是音频服务的内部实现结构体,由配置创建而来- 音频服务通过状态(
service_state_t
)和事件(service_event_t
)管理其生命周期和通知机制 - 各种回调函数类型(
service_ctrl
,service_callback
)定义了服务与应用程序的交互接口
资源管理函数分析
audio_service_create
audio_service_create
函数用于创建音频服务实例,分配必要的资源。下面是其源码实现:
/*** @brief 创建音频服务实例* * 该函数完成以下主要操作:* 1. 分配音频服务实例内存* 2. 初始化服务结构体,复制配置参数* 3. 复制服务名称(如果提供)* 4. 创建服务任务(如果配置了任务栈)* * 资源创建失败时会进行适当的清理,避免资源泄漏* * @param config 配置参数,包含回调函数、任务参数等信息* @return audio_service_handle_t 成功返回服务实例句柄,失败返回NULL*/
audio_service_handle_t audio_service_create(audio_service_config_t *config)
{// 检查配置参数是否为NULLAUDIO_NULL_CHECK(TAG, config, return NULL);// 分配服务实例内存audio_service_handle_t impl = audio_calloc(1, sizeof(audio_service_impl_t));AUDIO_MEM_CHECK(TAG, impl, return NULL);// 初始化服务结构体impl->service_start = config->service_start;impl->service_stop = config->service_stop;impl->service_connect = config->service_connect;impl->service_disconnect = config->service_disconnect;impl->service_destroy = config->service_destroy;impl->user_data = config->user_data;// 复制服务名称(如果提供)if (config->service_name) {impl->service_name = audio_strdup(config->service_name);AUDIO_MEM_CHECK(TAG, impl, goto serv_failed);}// 创建服务任务(如果配置了任务栈)if (config->task_stack > 0) {if (pdPASS != xTaskCreatePinnedToCore(config->task_func,config->service_name,config->task_stack,impl,config->task_prio,&impl->task_handle,config->task_core)) {ESP_LOGE(TAG, "Create task failed on %s", __func__);goto serv_failed;}}return impl;// 失败处理部分
serv_failed:// 释放已创建的资源audio_free(impl->service_name);impl->service_name = NULL;audio_free(impl);impl = NULL;return impl;
}
下面的时序图展示了 audio_service_create
函数的执行流程:
这个时序图清晰地展示了 audio_service_create
函数的执行流程,包括资源分配、结构体初始化、任务创建以及错误处理的过程。通过这个图可以直观地理解函数内部的调用关系和数据流向。
audio_service_destroy
audio_service_destroy
函数用于销毁音频服务实例,释放所有资源。下面是其源码实现:
/*** @brief 销毁音频服务实例并释放所有资源* * 该函数完成以下主要操作:* 1. 调用服务的销毁函数(如果提供)* 2. 释放服务名称内存* 3. 清除任务句柄* 4. 释放服务实例内存* * 函数确保所有在audio_service_create中分配的资源都被正确释放* * @param handle 服务实例句柄* @return esp_err_t 成功返回ESP_OK,失败返回错误码*/
esp_err_t audio_service_destroy(audio_service_handle_t handle)
{// 检查句柄是否有效AUDIO_NULL_CHECK(TAG, handle, return ESP_ERR_INVALID_ARG);// 获取服务实例audio_service_impl_t *impl = (audio_service_impl_t *) handle;// 调用服务的销毁函数(如果提供)if (impl->service_destroy) {impl->service_destroy(handle);}// 释放服务名称内存audio_free(impl->service_name);impl->service_name = NULL;// 清除任务句柄impl->task_handle = NULL;// 释放服务实例内存audio_free(impl);impl = NULL;return ESP_OK;
}
下面的时序图展示了 audio_service_destroy
函数的执行流程:
这个时序图清晰地展示了 audio_service_destroy
函数的执行流程,包括调用服务销毁函数和释放资源的过程。通过这个图可以直观地理解函数内部的调用关系和资源释放顺序。