我在使用esp-adf,起初我设计了两条pipeline但是,后期我为了简化流程,需要将两条pipeline顺序执行,有什么简单的办法可以做到阻塞同步?

47 2025-02-19 09:36

在使用 ESP-ADF(Espressif Audio Development Framework)时,如果你需要将两条 pipeline 顺序执行并实现阻塞同步,可以通过以下方法实现:

方法一:使用事件监听和状态判断

  1. 为每个 pipeline 设置事件监听器:通过 audio_event_iface_init 创建事件监听器,并将其与 pipeline 关联。
  2. 在主循环中监听事件:启动第一个 pipeline 后,进入循环监听其事件。当第一个 pipeline 的最后一个元素(如 i2s_stream_writer)报告停止事件时,退出循环。
  3. 启动第二个 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;
    }
}

方法二:使用信号量或互斥锁

  1. 创建信号量或互斥锁:在第一个 pipeline 的最后一个元素中,使用信号量或互斥锁来阻塞主线程。
  2. 释放信号量:当第一个 pipeline 执行完毕后,在其事件处理函数中释放信号量。
  3. 等待信号量:主线程在启动第一个 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 的顺序执行和阻塞同步。根据你的具体需求选择合适的方法即可。

全部评论

·