diff --git a/src/audio/component.c b/src/audio/component.c index af0b9c278368..c2df4ce09123 100644 --- a/src/audio/component.c +++ b/src/audio/component.c @@ -506,7 +506,7 @@ static bool comp_check_eos(struct comp_dev *dev) enum sof_audio_buffer_state sink_state = AUDIOBUF_STATE_INITIAL; struct comp_buffer *buffer; - if (!dev->pipeline->expect_eos) + if (!dev->expect_eos) return false; comp_dev_for_each_producer(dev, buffer) { diff --git a/src/audio/host-zephyr.c b/src/audio/host-zephyr.c index 5038bcc78320..58a22253f20d 100644 --- a/src/audio/host-zephyr.c +++ b/src/audio/host-zephyr.c @@ -396,7 +396,7 @@ static inline bool host_handle_eos(struct host_data *hd, struct comp_dev *dev, struct sof_audio_buffer *buffer = &hd->local_buffer->audio_buffer; enum sof_audio_buffer_state state = audio_buffer_get_state(buffer); - if (!dev->pipeline->expect_eos) + if (!dev->expect_eos) return false; if (!avail_samples) { diff --git a/src/audio/module_adapter/module/cadence.c b/src/audio/module_adapter/module/cadence.c index 672cef86c0a2..5d997d1c6433 100644 --- a/src/audio/module_adapter/module/cadence.c +++ b/src/audio/module_adapter/module/cadence.c @@ -541,7 +541,7 @@ int cadence_codec_process_data(struct processing_module *mod, return 0; } - if (dev->pipeline->expect_eos) { + if (dev->expect_eos) { /* Signal that the stream is expected to end anytime soon */ API_CALL(cd, XA_API_CMD_INPUT_OVER, 0, NULL, ret); if (ret != LIB_NO_ERROR) { @@ -596,7 +596,7 @@ int cadence_codec_process_data(struct processing_module *mod, return ret; } - if (dev->pipeline->expect_eos) { + if (dev->expect_eos) { /* * AAC decoder cannot signal DONE, check if it stopped * producing data when EOS is expected diff --git a/src/audio/pipeline/pipeline-graph.c b/src/audio/pipeline/pipeline-graph.c index e6f56eaf7096..7582eee1e53e 100644 --- a/src/audio/pipeline/pipeline-graph.c +++ b/src/audio/pipeline/pipeline-graph.c @@ -344,6 +344,39 @@ int pipeline_free(struct pipeline *p) return 0; } +static int pipeline_comp_set_eos(struct comp_dev *current, + struct comp_buffer *calling_buf, + struct pipeline_walk_context *ctx, int dir) +{ + if (ctx->comp_data != (void *)current->pipeline) + return 0; + + current->expect_eos = *(bool *)ctx->buff_data; + + return pipeline_for_each_comp(current, ctx, dir); +} + +void pipeline_set_eos(struct pipeline *p, bool eos) +{ + struct pipeline_walk_context walk_ctx = { + .comp_func = pipeline_comp_set_eos, + .comp_data = p, + .buff_data = &eos, + }; + struct comp_dev *start; + int dir; + + if (p->source_comp->direction == SOF_IPC_STREAM_PLAYBACK) { + dir = PPL_DIR_UPSTREAM; + start = p->sink_comp; + } else { + dir = PPL_DIR_DOWNSTREAM; + start = p->source_comp; + } + + walk_ctx.comp_func(start, NULL, &walk_ctx, dir); +} + static int pipeline_comp_complete(struct comp_dev *current, struct comp_buffer *calling_buf, struct pipeline_walk_context *ctx, int dir) diff --git a/src/include/sof/audio/component.h b/src/include/sof/audio/component.h index 672603e430c7..48d0764f26d8 100644 --- a/src/include/sof/audio/component.h +++ b/src/include/sof/audio/component.h @@ -647,6 +647,7 @@ struct comp_dev { /* runtime */ uint16_t state; /**< COMP_STATE_ */ uint32_t frames; /**< number of frames we copy to sink */ + bool expect_eos; /**< end of stream expected */ struct pipeline *pipeline; /**< pipeline we belong to */ struct task *task; /**< component's processing task used diff --git a/src/include/sof/audio/pipeline.h b/src/include/sof/audio/pipeline.h index 858c81d98a2f..1b704ed83fe1 100644 --- a/src/include/sof/audio/pipeline.h +++ b/src/include/sof/audio/pipeline.h @@ -70,7 +70,6 @@ struct pipeline { int32_t xrun_bytes; /* last xrun length */ uint32_t status; /* pipeline status */ struct tr_ctx tctx; /* trace settings */ - bool expect_eos; /* pipeline is expecting end of stream */ /* scheduling */ #ifdef CONFIG_IPC_MAJOR_4 @@ -225,6 +224,13 @@ void pipeline_posn_grant_access(struct k_thread *thread); */ int pipeline_reset(struct pipeline *p, struct comp_dev *host_cd); +/** + * \brief Sets End Of Stream state for all devices in the pipeline. + * \param[in] p pipeline. + * \param[in] eos End Of Stream state. + */ +void pipeline_set_eos(struct pipeline *p, bool eos); + /** * \brief Walks the pipeline graph for each component. * \param[in] current Current pipeline component. diff --git a/src/ipc/ipc4/handler-user.c b/src/ipc/ipc4/handler-user.c index c14bbe7a7ce5..5cea1bf7dbe4 100644 --- a/src/ipc/ipc4/handler-user.c +++ b/src/ipc/ipc4/handler-user.c @@ -256,7 +256,7 @@ int ipc4_pipeline_prepare(struct ipc_comp_dev *ppl_icd, uint32_t cmd) switch (cmd) { case SOF_IPC4_PIPELINE_STATE_RUNNING: - if (ppl_icd->pipeline->expect_eos) { + if (ppl_icd->pipeline->source_comp && ppl_icd->pipeline->source_comp->expect_eos) { ipc_cmd_err(&ipc_tr, "pipeline %d: Can't transition from EOS to RUNNING", ppl_icd->id); return IPC4_INVALID_REQUEST; @@ -320,7 +320,7 @@ int ipc4_pipeline_prepare(struct ipc_comp_dev *ppl_icd, uint32_t cmd) ppl_icd->id, status); return IPC4_INVALID_REQUEST; } - ppl_icd->pipeline->expect_eos = true; + pipeline_set_eos(ppl_icd->pipeline, true); return 0; /* Must return here. Any other transition clears expect_eos. */ /* special case - TODO */ case SOF_IPC4_PIPELINE_STATE_SAVED: @@ -334,7 +334,7 @@ int ipc4_pipeline_prepare(struct ipc_comp_dev *ppl_icd, uint32_t cmd) if (ret < 0) return IPC4_INVALID_REQUEST; - ppl_icd->pipeline->expect_eos = false; + pipeline_set_eos(ppl_icd->pipeline, false); return ret; } diff --git a/test/cmocka/src/audio/mux/demux_copy.c b/test/cmocka/src/audio/mux/demux_copy.c index 8e331446bbf4..cb789707306f 100644 --- a/test/cmocka/src/audio/mux/demux_copy.c +++ b/test/cmocka/src/audio/mux/demux_copy.c @@ -169,7 +169,7 @@ static int setup_test_case(void **state) dummy_pipe = test_malloc(sizeof(*dummy_pipe)); if (!dummy_pipe) return -ENOMEM; - dummy_pipe->expect_eos = false; + dev->expect_eos = false; dev->pipeline = dummy_pipe; mod = comp_mod(dev); diff --git a/test/cmocka/src/audio/mux/mux_copy.c b/test/cmocka/src/audio/mux/mux_copy.c index 66b21b0df27c..a4c42f99e94e 100644 --- a/test/cmocka/src/audio/mux/mux_copy.c +++ b/test/cmocka/src/audio/mux/mux_copy.c @@ -191,7 +191,7 @@ static int setup_test_case(void **state) dummy_pipe = test_malloc(sizeof(*dummy_pipe)); if (!dummy_pipe) return -ENOMEM; - dummy_pipe->expect_eos = false; + dev->expect_eos = false; dev->pipeline = dummy_pipe; mod = comp_mod(dev);