-
Notifications
You must be signed in to change notification settings - Fork 349
pipeline param negotiation #2788
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
pipeline param negotiation #2788
Conversation
keyonjie
commented
Apr 17, 2020
lgirdwood
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
src/audio/pipeline.c
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you put the calling_buf in ctx
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, after think it more, @lgirdwood I think it's better to keep this calling_buf outside of the ctx, as the all the other ctx members are constant during the whole path walking, while this calling_buf is keep changing.
So better not to store it in the ctx otherwise it will be lost as the deeper layer will overwrite and break the upper layer value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, what's the usage of calling_buf. Is it the current or next or previous source/sink buffer in the pipeline ? It sounds like we need to rename to better reflect the usage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, what's the usage of calling_buf. Is it the current or next or previous source/sink buffer in the pipeline ? It sounds like we need to rename to better reflect the usage.
It is the buffer ahead of the 'current' component, it could be one of the current component's source/sink buffer in the pipeline, depends on what direction we are walking in. the calling_buf is used to check and make sure we are not iterating to the path which we have done to avoid dead loop, for example, in below path, we are walking .params() in this way: b1-> comp 1 -> params negotiation with b2, b3(b1 is excluded here for it is the calling_buf) done --> b3:
b3--------|
v
b1 -> comp 1 --> b3
^
b2--------|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, this is really then the "next_buf". To avoid re-walking the same components you should add a member to component or buffer that is a flag for "walked already"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, this is really then the "next_buf". To avoid re-walking the same components you should add a member to component or buffer that is a flag for "walked already"
I think it is not the "next", it should be the "previous"? adding a flag could be a choice, but then we might need to manage state of this flag (e.g. we need to do one more iteration to reset all of them once the walking is done, we even need to do this several times in one .params() of the pipeline, as you may know that the pipeline_comp_hw_params() is doing one more iteration before the real pipeline_comp_hw_params() is called).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DAPM uses a "walked" flag when traversing the graph. It's reset before every walk. Please do the same here, sinec the DAPM version also survives loops (and this PR wont)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can add this flag to buffer only (no need for component), but to reset before every walk(e.g. .params(), .prepare(), .trigger(), .reset(), .copy()), we need to add a full iteration (to all buffers belong to or connected to the pipeline under iterated) ahead respectively, is this what you expected @lgirdwood ?
Sure, I am preparing documentation on how this works, I can add it to sof-docs when @kv2019i's one is available. |
src/audio/pipeline.c
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It runs in the ppl_data->p context, so use pipe_dbg(ppl_data->p, "....", ...) to include the pipeline id in the trace messages.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, I just followed the existed ones in pipeline_comp_params() and pipeline_comp_hw_params(), fwiw, let me change it to pipe_dbg.
src/audio/pipeline.c
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use pipe_err()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure.
src/include/sof/audio/buffer.h
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Trace message does not explain what happened. I am also not sure whether this is real run-time error, expected scenario (the message should be a warning at most then), or a logic error (and assert() should be used here)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mmaka1 Asserts cannot be used as sole verification, because they can be disabled. Not yet, but once we will move to Zephyr we will be able to disable asserts. So if it's a logic error, we shouldn't have just assert but also this trace and return.
And actually... We shouldn't assert on parameters that are controlled by the Linux driver, but only internal values. Asserting on an external guarantee (something the Linux driver "guarantees" is never a good idea, because mismatched versions will occur).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@paulstelian97 I assume that asserts may be compiled out of the production code, so they should be use to catch logic errors only (those coming from coding issues) during the code bringup and debug phase. Any data coming from the driver should be verified at run-time. However I asked about this particular case, afair the parameters in this flow are internally computed by the fw, so I asked to double check whether tracing run-time error makes sense in this case. Still not sure what response is expected when seeing this error message in the trace log.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we don't know for certain this is internally computed, assume it isn't. That's the thing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mmaka1 @paulstelian97 Thanks for the comments.
I was not sure how the helper will be used and what params and buffer it could be passed in, so I treated it as run-time error here.
But after thought about it more now, as @mmaka1 stated, here what we tried to catch here is the code logic error(e.g. some calling to buffer_params_match() with NULL buffer or params) but not the run-time params errors from the Linux kernel side, the response should be halting the execution of the FW but not just returning an false when this error happen, so changing it to 'assert' handling looks good to me.
82129fa to
16a9b5c
Compare
|
@paulstelian97 @mmaka1 @lgirdwood comments are addressed, please help to re-review, thanks. |
bkokoszx
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@keyonjie
We can see that our TestDemuxSynchronizedCapture48000Hz24b32b4ch are failing. Those tests are using following topology:
pipe_plb
+-------------------------------+
| +------+ +------+ +-----+ | +------+
| | Host |-->| Buff |-->| Dai |-------------------------------------------------->| SSPx |
| +------+ +------+ +-----+ | +------+
+-------------------------------+ |
|
|
pipe_cap |
+----------------------------------------------------------------------------+ |
| +-------+ +------+ +-----+ +------+ +-------+ +------+ +-----+ | +------+
| | Host1 |<--| B1.0 |<--| Vol |<--| B1.1 |<--| DeMux |<--| B1.2 |<--| Dai |<-----| SSPx |
| +-------+ +------+ +-----+ +------+ +-------+ +------+ +-----+ | +------+
+-------------------------------------------------|--------------------------+
|
pipe_cap |
+-------------------------------------------+ |
| +-------+ +------+ +-----+ +------+ | |
| | Host2 |<--| B2.0 |<--| Vol |<--| B2.1 |<------+
| +-------+ +------+ +-----+ +------+ |
+-------------------------------------------+
, where capture Host1 has 48 kHz, 16/16 frame_fmt, 4 channels stream and Host2 has 48 kHz, 16/16 frame_fmt, 8 channels.
It is failing on a captured streams verification. This happens, because we do not have B1.1 well configured. Firstly, we send pcm params to Host1 and configure B1.1 with 4 channels stream, next we send pcm params to Host2 and in pipeline_comp_params_neg() we overwrite ```B1.1`` with 8 channels, which results in a mismatch in channels parameter.
In my opinion, we should add condition ensuring that we wouldn't negotiate params between pipelines working in the same direction. Something like:
diff --git a/src/audio/pipeline.c b/src/audio/pipeline.c
index c381174b2..d7a8701eb 100644
--- a/src/audio/pipeline.c
+++ b/src/audio/pipeline.c
@@ -388,6 +388,10 @@ static int pipeline_comp_params_neg(struct comp_dev *current,
pipe_dbg(ppl_data->p, "pipeline_comp_params_neg(), current->comp.id = %u, dir = %u",
dev_comp_id(current), dir);
+ if (current->state == COMP_STATE_PREPARE &&
+ current->direction == ppl_data->params->params.direction)
+ return err;
+
/* return if current is running */
if (current->state == COMP_STATE_ACTIVE) {
if (buffer_params_match(calling_buf,
Thanks for trying this, I think you params the 2nd stream before the 1st one is started, right, this do uncover a bug in the state check, can you try if below change help? |
16a9b5c to
fe42edb
Compare
|
@bkokoszx the new component state coverage is added. |
src/audio/pipeline.c
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"further" what ?, can you provide context.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo, should be the propagation "go further".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"further" what ?, can you provide context.
fixed.
|
Due to recent PR3194 merge, please rebase for TGL Multicore tests to Pass on Internal CI. |
lgirdwood
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@keyonjie ping
|
@lgirdwood @mmaka1 @bkokoszx I am not sure if we still need this change for demux/smart_amp usage scenarios? |
|
@keyonjie dont think so. Lets close, we can re-open if needed. |
|
@lgirdwood |
91d864d to
5a033f8
Compare
|
@lgirdwood rebased to the latest base. How should we proceed for this now? |
5a033f8 to
5bec139
Compare
keyonjie
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lgirdwood we still need this fix for components like demux which could have multiple inputs/outputs, just updated it and addressed what remained, please help to review.
src/audio/pipeline.c
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"further" what ?, can you provide context.
fixed.
src/audio/pipeline.c
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment does not align with the code below
src/audio/pipeline.c
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean walk the new pipeline here. I think at this point the connected pipeline source buffer will have the correct params configured so no further action would be needed. This can be removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we stop here after the connected (but not paramed) pipeline source buffer is propagated.
We might need to propagate it forward in the future, but no this requirement for now.
OK, let me remove this comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's still there.
5bec139 to
d779ae5
Compare
lgirdwood
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just minor.
src/audio/pipeline.c
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's still there.
Add a helper buffer_param_match() to check if the configured runtime buffer frame format/rate/channels are matched to the param ones Signed-off-by: Keyon Jie <yang.jie@linux.intel.com>
Add a flag 'walking' to the buffer struct, to indicate if the buffer is just being traversed while walking through the graph, and don't go back to the buffer which is already walked. Signed-off-by: Keyon Jie <yang.jie@linux.intel.com>
For different connected pipelines, they are usually connected via a component with >1 source or sink buffers, as most of those components don't have ability to converse frame format or sample rate, we need add a params negotiation mechanism between those pipelines. If all buffers are iterated in the params propagation direction, no negotiation needed, otherwise we need to iterate all other buffers in the opposite direction, to make sure all connected buffers have chance to take part in the negotiation. The negotiation should happen before we can propagate the params further, when doing negotiation in a branch/buffer, we should check: If a branch is active, check if params is matched, return error to reject the whole .params() requirement if not. If a branch is inactive, force update the params to its calling buffer, to make sure all branches are aligned on the format. We are propagating the params to branched buffer, and the subsequent component's .params() or .prepare() should be responsible to calibrate the buffer params if needed. For example, a component who has different channels buffers should explicitly configure the channels for its branched buffers (the ones connected to another pipeline). Signed-off-by: Keyon Jie <yang.jie@linux.intel.com>
d779ae5 to
49e9c72
Compare