|
5 | 5 | // Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> |
6 | 6 |
|
7 | 7 | #include <sof/audio/component_ext.h> |
| 8 | +#include <sof/audio/sink_source_utils.h> |
8 | 9 | #include <sof/common.h> |
9 | 10 | #include <sof/debug/telemetry/performance_monitor.h> |
10 | 11 | #include <rtos/panic.h> |
@@ -496,6 +497,62 @@ void audio_stream_copy_to_linear(const struct audio_stream *source, int ioffset, |
496 | 497 | } |
497 | 498 | } |
498 | 499 |
|
| 500 | +static bool comp_check_eos(struct comp_dev *dev) |
| 501 | +{ |
| 502 | + enum sof_audio_buffer_state sink_state = AUDIOBUF_STATE_INITIAL; |
| 503 | + struct comp_buffer *buffer; |
| 504 | + |
| 505 | + if (!dev->pipeline->expect_eos) |
| 506 | + return false; |
| 507 | + |
| 508 | + comp_dev_for_each_producer(dev, buffer) { |
| 509 | + struct sof_source *source = audio_buffer_get_source(&buffer->audio_buffer); |
| 510 | + enum sof_audio_buffer_state state = source_get_state(source); |
| 511 | + |
| 512 | + if (source_get_pipeline_id(source) != dev->pipeline->pipeline_id) |
| 513 | + continue; |
| 514 | + |
| 515 | + if (state == AUDIOBUF_STATE_END_OF_STREAM_FLUSH) { |
| 516 | + /* Earlier in the pipeline, there is a DP module that has reached |
| 517 | + * the EOS state. However, silence is generated to flush its internal |
| 518 | + * buffers, so pass this state to the output buffers. |
| 519 | + */ |
| 520 | + comp_dbg(dev, "comp_check_eos() - EOS flush detected"); |
| 521 | + sink_state = AUDIOBUF_STATE_END_OF_STREAM_FLUSH; |
| 522 | + break; |
| 523 | + } else if (state == AUDIOBUF_STATE_END_OF_STREAM) { |
| 524 | + /* EOS is detected, so we need to set the sink state to AUDIOBUF_STATE_EOS. */ |
| 525 | + size_t min_avail = source_get_min_available(source); |
| 526 | + |
| 527 | + if (source_get_data_available(source) < min_avail) { |
| 528 | + comp_dbg(dev, "comp_check_eos() - EOS detected"); |
| 529 | + if (dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP) { |
| 530 | + /* For DP modules, fill missing input data with silence to |
| 531 | + * allow it to process the remaining data. |
| 532 | + */ |
| 533 | + struct sof_sink *previous_mod_data_sink = |
| 534 | + audio_buffer_get_sink(&buffer->audio_buffer); |
| 535 | + sink_fill_with_silence(previous_mod_data_sink, min_avail); |
| 536 | + sink_state = AUDIOBUF_STATE_END_OF_STREAM_FLUSH; |
| 537 | + } else { |
| 538 | + sink_state = AUDIOBUF_STATE_END_OF_STREAM; |
| 539 | + break; |
| 540 | + } |
| 541 | + } |
| 542 | + } |
| 543 | + } |
| 544 | + |
| 545 | + if (sink_state != AUDIOBUF_STATE_INITIAL) { |
| 546 | + comp_dev_for_each_consumer(dev, buffer) |
| 547 | + audio_buffer_set_state(&buffer->audio_buffer, sink_state); |
| 548 | + |
| 549 | + /* For AUDIOBUF_STATE_END_OF_STREAM_FLUSH process data normally. */ |
| 550 | + return sink_state != AUDIOBUF_STATE_END_OF_STREAM_FLUSH; |
| 551 | + } |
| 552 | + |
| 553 | + return false; |
| 554 | +} |
| 555 | + |
499 | 556 | /** See comp_ops::copy */ |
500 | 557 | int comp_copy(struct comp_dev *dev) |
501 | 558 | { |
@@ -530,6 +587,9 @@ int comp_copy(struct comp_dev *dev) |
530 | 587 | const uint32_t begin_stamp = (uint32_t)telemetry_timestamp(); |
531 | 588 | #endif |
532 | 589 |
|
| 590 | + if (comp_check_eos(dev)) |
| 591 | + return 0; |
| 592 | + |
533 | 593 | ret = dev->drv->ops.copy(dev); |
534 | 594 |
|
535 | 595 | #ifdef CONFIG_SOF_TELEMETRY_PERFORMANCE_MEASUREMENTS |
|
0 commit comments