我在使用esp-adf,起初我设计了两条pipeline但是,后期我为了简化流程,需要将两条pipeline顺序执行,有什么简单的办法可以做到阻塞同步?
47 2025-02-19 09:36
在使用 ESP-ADF(Espressif Audio Development Framework)时,如果你需要将两条 pipeline 顺序执行并实现阻塞同步,可以通过以下方法实现:
方法一:使用事件监听和状态判断
-
为每个 pipeline 设置事件监听器:通过
audio_event_iface_init
创建事件监听器,并将其与 pipeline 关联。 -
在主循环中监听事件:启动第一个 pipeline 后,进入循环监听其事件。当第一个 pipeline 的最后一个元素(如
i2s_stream_writer
)报告停止事件时,退出循环。 -
启动第二个 pipeline:在第一个 pipeline 停止后,启动第二个 pipeline,并重复上述监听逻辑。
示例代码片段:
c复制
// 初始化事件监听器
audio_event_iface_cfg_t evt_cfg = AUDIO_EVENT_IFACE_DEFAULT_CFG();
audio_event_iface_handle_t evt1 = audio_event_iface_init(&evt_cfg);
audio_event_iface_handle_t evt2 = audio_event_iface_init(&evt_cfg);
// 将事件监听器与 pipeline 关联
audio_pipeline_set_listener(pipeline1, evt1);
audio_pipeline_set_listener(pipeline2, evt2);
// 启动第一个 pipeline
audio_pipeline_run(pipeline1);
// 监听第一个 pipeline 的事件
while (1) {
audio_event_iface_msg_t msg;
esp_err_t ret = audio_event_iface_listen(evt1, &msg, portMAX_DELAY);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Event interface error: %d", ret);
continue;
}
if (msg.source_type == AUDIO_ELEMENT_TYPE_ELEMENT && msg.source == (void*)i2s_stream_writer1 &&
msg.cmd == AEL_MSG_CMD_REPORT_STATUS && (int)msg.data == AEL_STATUS_STATE_STOPPED) {
ESP_LOGW(TAG, "Pipeline 1 stopped");
break;
}
}
// 启动第二个 pipeline
audio_pipeline_run(pipeline2);
// 监听第二个 pipeline 的事件
while (1) {
audio_event_iface_msg_t msg;
esp_err_t ret = audio_event_iface_listen(evt2, &msg, portMAX_DELAY);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Event interface error: %d", ret);
continue;
}
if (msg.source_type == AUDIO_ELEMENT_TYPE_ELEMENT && msg.source == (void*)i2s_stream_writer2 &&
msg.cmd == AEL_MSG_CMD_REPORT_STATUS && (int)msg.data == AEL_STATUS_STATE_STOPPED) {
ESP_LOGW(TAG, "Pipeline 2 stopped");
break;
}
}
方法二:使用信号量或互斥锁
-
创建信号量或互斥锁:在第一个 pipeline 的最后一个元素中,使用信号量或互斥锁来阻塞主线程。
-
释放信号量:当第一个 pipeline 执行完毕后,在其事件处理函数中释放信号量。
-
等待信号量:主线程在启动第一个 pipeline 后,等待信号量被释放,然后启动第二个 pipeline。
示例代码片段:
c复制
// 创建信号量
xSemaphoreHandle sem = xSemaphoreCreateBinary();
// 第一个 pipeline 的事件处理函数
void pipeline1_event_handler(audio_event_iface_msg_t *msg) {
if (msg->source_type == AUDIO_ELEMENT_TYPE_ELEMENT && msg->source == (void*)i2s_stream_writer1 &&
msg->cmd == AEL_MSG_CMD_REPORT_STATUS && (int)msg->data == AEL_STATUS_STATE_STOPPED) {
xSemaphoreGive(sem); // 释放信号量
}
}
// 主线程
audio_pipeline_run(pipeline1);
xSemaphoreTake(sem, portMAX_DELAY); // 等待信号量
audio_pipeline_run(pipeline2);
方法三:合并为一个 pipeline
如果两条 pipeline 的功能可以合并,可以考虑将它们合并为一个 pipeline,从而避免同步问题。这种方法需要重新设计 pipeline 的结构,但可以简化代码逻辑。
通过以上方法,你可以实现两条 pipeline 的顺序执行和阻塞同步。根据你的具体需求选择合适的方法即可。
全部评论