-
Notifications
You must be signed in to change notification settings - Fork 311
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
capture pause/release failure when play/capture work at same time #35
Conversation
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 looks good to me, good catch and fix, Liam, we need this, please help review and merge it.
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.
good catch, but lets also remove the old capture data so we dont send it to the host.
@@ -223,6 +222,22 @@ static void pipeline_trigger_sched_comp(struct pipeline *p, | |||
} | |||
} | |||
break; | |||
case COMP_TRIGGER_RELEASE: |
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 in the right direction, but instead of scheduling the pipeline to fix this issue with old data we should actually reset the pipeline buffers (i.e. clear the buffers to 0s and reset their R/W ptr to initial start positions). This way we recover without XRUN and we do not send stale/old capture data to the host (as pause can be longer than a few seconds).
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 is for the pause/release process. If we do it like this. What is different between the stop/start and pause/release. Should we merge them?
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, should be merged. Capture stop/start and pause/release have same flow, i.e we discard old data and reset R/W pts.
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 will send the next version.
I think the playback also has the same case, right?
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.
no, playback should not clear the buffers on pause, only on stop
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.
I think it is not big issue that we don't clear buffers on capture pause? in that way, those captured data(in buffer) will be written to application somewhat late only, those data still make sense.
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.
no, that's wrong. if you are recording a conversation and then pause for 5 seconds you do not expect the first few periods after resume to contain audio from 5 secs ago as they will be out of context and may even cause audible artifacts.
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.
but think from another side, if we reset buffers there may be milliseconds data lost, it is also another kind of artifacts?
and, the case you listed above may happen for playback also, considering live playback, if we don't reset buffer for pause on playback, we may also hear out of context audio which may also cause audible artifacts.
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.
What about another solution:
Still scheduling the pipeline to fix this bug, but when pause the pipeline, we clear the buffer to 0s. do not reset the R/W ptr.
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.
I dont mind if we bzero at pause or release for capture, maybe easier at release since we are not waiting for any DMA completions.
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.
Some more details please.
src/audio/dai.c
Outdated
dma_status(dd->dma, dd->chan, | ||
&status, SOF_IPC_STREAM_CAPTURE); | ||
|
||
if (status.w_pos != (uint32_t)dma_buffer->w_ptr) |
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.
Why do you release the DMA in the callback if stream is not active ?
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.
When the pipeline is paused, this is last time we reach here before release the pipeline.
over here, we reset the buffer pointer, call the dma_release() to adjust the dma pointer.
then ready for the release command coming.
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.
Consider a DAI capture buffer B with 2 periods p0, p1. At release the downstream pipeline will consume 0s from p0 whilst the DMA is filling p1. Once p1 is full DMA will IRQ and then the DMA will fill p0 and pipeline will consume valid data from p1 (and so on...)
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.
Actually we did not schedule the capture pipeline when we do the start/release. the capture's pipeline is scheduled when the DMA finish filling one period buffer. At the beginning stage, the downstream pipeline is not working, only the dai DMA is doing the data filling.
So we have to reset the buffer pointer and DMA pointer over here.
src/audio/dai.c
Outdated
*/ | ||
if (dev->params.direction == SOF_IPC_STREAM_PLAYBACK) { | ||
/* recover the dma status */ | ||
ret = dma_release(dd->dma, dd->chan); |
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.
Where do we release() capture stream ?
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.
When the release command comes, we did not need to do the dma pointer again(by calling dma_release() function). because we adjust the dma pointer in dai_dma_cb() function already.
src/audio/host.c
Outdated
dma_status(hd->dma, hd->chan, | ||
&status, SOF_IPC_STREAM_CAPTURE); | ||
if (status.r_pos != | ||
((uint32_t)hd->dma_buffer->r_ptr & 0x00FFFFFF)) { |
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.
Why do we & 0xffffff 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.
because the HOST DMA's DGBRP only has the bit0~bit23 valid.
I will replace it with macro.
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 is DMA specific, it should be done by dma_status API on r_pos.
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.
I will confirm it by trace log.
src/audio/host.c
Outdated
* just adjust the buffer pointer to sync | ||
* with host dma's register pointer. | ||
*/ | ||
hd->dma_buffer->r_ptr += hd->dma_buffer->size; |
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.
The comments say what you are doing but dont say why ?
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 will update it in the commit description.
Let me describe it over here before:
the host buffer pointer should be sync with host dma pointer. because we did not stop the host dma, we have to read the DGBRP pointer first, then adjust the host buffer pointer according to the DGBRP pointer value.
|
|
|
If we did not reset the R/W pointer, we only clear the buffer to 0s before release. |
Capturing a period full of 0s at start or release is fine. |
In these three RFCs, we do several things:
|
Ok, so it sounds like you have a plan with 3 changes so best to send 3 patches in the PR update. i.e. 1 patch for each change above. |
this is the patch set for this issue fix, this must be merged in one time. |
I update the patches already. this is the cluster patch. we should not divide them into three PRs. |
@@ -223,6 +222,22 @@ static void pipeline_trigger_sched_comp(struct pipeline *p, | |||
} | |||
} | |||
break; | |||
case COMP_TRIGGER_RELEASE: |
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.
I dont mind if we bzero at pause or release for capture, maybe easier at release since we are not waiting for any DMA completions.
src/audio/buffer.c
Outdated
@@ -100,6 +100,13 @@ void buffer_free(struct comp_buffer *buffer) | |||
rfree(buffer); | |||
} | |||
|
|||
void buffer_zero(struct comp_buffer *buffer) |
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.
static inline
updated according to the comments 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.
Please fix all your commit messages to use your Intel affiliation. The following tag is not acceptable:
Signed-off-by: Wu Zhigang wzgpeter@163.com
the issue case: playback and capture work at same time. when pause and resume the capture, the DSP will enter panic. the issue analysis: when pause the capture pipeline, the capture's last dma interrupt happens, and the capture will be paused. at this time, each buffer in capture pipeline will have the data unprocessed, sometimes it might be full. if we did not trigger the capture pipeline in resume process, the coming dma interrupt will have the xrun in the buffer pointer update. it is the high possibility. Signed-off-by: Wu Zhigang <zhigang.wu@linux.intel.com>
add the buffer_zero() function, we can use it when we want to clear the buffer data to 0s without resetting the buffer R/W pointer. Signed-off-by: Wu Zhigang <zhigang.wu@linux.intel.com>
before the capture pipeline is released, we should zero the dai buffer data. then the history data will not be sent out after release. Signed-off-by: Wu Zhigang <zhigang.wu@linux.intel.com>
update it already. |
Please add a description.