Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/audio/module_adapter/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@ sequenceDiagram
deactivate DP
```

A sinkless DP module derives its period from the first source's
`min_available` value (its IBS) and audio format. This schedules input-only
detectors according to data arrival; a zero or otherwise invalid period is
rejected by the normal minimum-period check during prepare.

## Error Handling and Memory Sandboxing

* **Sandboxing (`mod_balloc_align`, `z_impl_mod_fast_get`, `z_impl_mod_free`)**: Since third-party DSP code is treated as semi-untrusted in memory lifetimes, module allocations grab slices from a dedicated component `dp_heap_user` heap instead of the global system heap (`mod_heap_info`). The wrapper automatically prunes leaked objects (`mod_free_all(mod)`) during teardown by keeping an `objpool` of all resource containers.
Expand Down
7 changes: 6 additions & 1 deletion src/audio/module_adapter/iadk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,12 @@ A significant task of `IadkModuleAdapter_Process` is converting SOF's underlying

Instead of letting the module directly touch the SOF `comp_buffer` (which could change with SOF version updates), the adapter uses the abstraction APIs (`source_get_data` / `sink_get_buffer`) and wraps them:

1. Request raw continuous memory pointers from `source_get_data()`.
1. Limit each input to one source `min_available` portion (one IBS), then
request its continuous memory pointer from `source_get_data()`.
2. Construct an `intel_adsp::InputStreamBuffer` pointing to that continuous memory chunk.
3. Call the IADK `processing_module_.Process()`.
4. Release precisely the amount of consumed data using `source_release_data()`.

Input-only detector endpoints are processed even when no audio sink is
connected. Their output descriptors remain empty, so the module can consume
and inspect each IBS without producing downstream audio.
8 changes: 6 additions & 2 deletions src/audio/module_adapter/iadk/iadk_module_adapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ int IadkModuleAdapter::IadkModuleAdapter_Process(struct sof_source **sources,
{
int ret = 0;

if ((num_of_sources > 0) && (num_of_sinks > 0)) {
if (num_of_sources > 0) {
intel_adsp::InputStreamBuffer input_stream_buffers[INPUT_PIN_COUNT];
intel_adsp::OutputStreamBuffer output_stream_buffers[OUTPUT_PIN_COUNT];
for (int i = 0; i < (int)num_of_sources; i++) {
Expand All @@ -55,6 +55,11 @@ int IadkModuleAdapter::IadkModuleAdapter_Process(struct sof_source **sources,

intel_adsp::InputStreamFlags flags = {};
i_size = source_get_data_available(sources[i]);
size_t min_available = source_get_min_available(sources[i]);

if (min_available && i_size > min_available)
i_size = min_available;

ret = source_get_data(sources[i], i_size, (const void **)&input,
(const void **)&input_start, &input_end);
if (ret != 0)
Expand Down Expand Up @@ -255,4 +260,3 @@ void* operator new(size_t size, intel_adsp::OutputStreamBuffer* placeholder) thr
return placeholder;
}
#endif

22 changes: 20 additions & 2 deletions src/audio/module_adapter/module_adapter.c
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,18 @@ static void module_adapter_calculate_dp_period(struct comp_dev *dev)

}

/* Sinkless modules derive their deadline from one input buffer. */
if (period == UINT32_MAX && mod->num_of_sources > 0) {
size_t frame_bytes = source_get_frame_bytes(mod->sources[0]);
unsigned int rate = source_get_rate(mod->sources[0]);

if (frame_bytes && rate)
period = 1000000ULL * source_get_min_available(mod->sources[0]) /
(frame_bytes * rate);
else
period = 0;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

previously in this case dev->period would be set to UINT32_MAX. Is this change deliberate? What's its purpose? This seems to be an error case anyway, right?

}

dev->period = period;
}
#endif /* CONFIG_ZEPHYR_DP_SCHEDULER */
Expand Down Expand Up @@ -473,12 +485,18 @@ int module_adapter_prepare(struct comp_dev *dev)
* Hence check for NULL.
*/
sink = comp_dev_get_first_data_consumer(dev);
if (!sink) {
if (!sink && !IS_PROCESSING_MODE_SINK_SOURCE(mod)) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are sinkless modules only allowed in DP mode or in LL too?

comp_err(dev, "no sink present on period size calculation");
return -EINVAL;
}

mod->period_bytes = audio_stream_period_bytes(&sink->stream, dev->frames);
/* A sinkless module still needs at least one source. */
if (!sink && !comp_dev_get_first_data_producer(dev)) {
comp_err(dev, "no source or sink buffer connected");
return -EINVAL;
}

mod->period_bytes = sink ? audio_stream_period_bytes(&sink->stream, dev->frames) : 0;
comp_dbg(dev, "got period_bytes = %u", mod->period_bytes);

/* no more to do for sink/source mode */
Expand Down
Loading