On Wed, 2017-06-28 at 13:32 +0300, Seppo Ingalsuo wrote:
SRC updates sink and downstream pipeline PCM rate, period_count and period_bytes in src_params() according to received out_rate via IPC. Also the use of incorrect alloc_size is replaced by ipc_buffer.size.
Signed-off-by: Seppo Ingalsuo seppo.ingalsuo@linux.intel.com
src/audio/src.c | 90 ++++++++++++++++++++++++----------------- src/include/reef/audio/buffer.h | 8 ++-- src/include/uapi/ipc.h | 1 + 3 files changed, 57 insertions(+), 42 deletions(-)
diff --git a/src/audio/src.c b/src/audio/src.c index c338220..f1f4b86 100644 --- a/src/audio/src.c +++ b/src/audio/src.c @@ -56,9 +56,13 @@ /* src component private data */ struct comp_data { struct polyphase_src src[PLATFORM_MAX_CHANNELS];
- /* Next two elements must be kept in this order since
* the end of pcm_params is a flexible array.
*/
- struct sof_ipc_pcm_params pcm_params;
- enum sof_ipc_chmap channel_map[PLATFORM_MAX_CHANNELS]; int32_t *delay_lines; int scratch_length;
- //int32_t z[STAGE_BUF_SIZE]; void (*src_func)(struct comp_dev *dev, struct comp_buffer *source, struct comp_buffer *sink,
@@ -155,7 +159,7 @@ static void src_2s_s32_default(struct comp_dev *dev,
s1.times = n_times1; s1.x_end_addr = source->end_addr;
- s1.x_size = source->alloc_size;
- s1.x_size = source->ipc_buffer.size;
buffer size is correct, the alloc size is the size actually returned by the allocator an may be larger than the requested buffer size (since the allocator only allocates on discrete sizes).
s1.x_inc = nch; s1.y_end_addr = &cd->delay_lines[cd->scratch_length]; s1.y_size = STAGE_BUF_SIZE * sizeof(int32_t); @@ -166,7 +170,7 @@ static void src_2s_s32_default(struct comp_dev *dev, s2.x_size = STAGE_BUF_SIZE * sizeof(int32_t); s2.x_inc = 1; s2.y_end_addr = sink->end_addr;
- s2.y_size = sink->alloc_size;
s2.y_size = sink->ipc_buffer.size; s2.y_inc = nch;
s1.x_rptr = src + nch - 1;
@@ -227,10 +231,10 @@ static void src_1s_s32_default(struct comp_dev *dev,
s1.times = n_times; s1.x_end_addr = source->end_addr;
- s1.x_size = source->alloc_size;
- s1.x_size = source->ipc_buffer.size; s1.x_inc = nch; s1.y_end_addr = sink->end_addr;
- s1.y_size = sink->alloc_size;
- s1.y_size = sink->ipc_buffer.size; s1.y_inc = nch; s1.x_rptr = src + nch - 1; s1.y_wptr = dest + nch - 1;
@@ -263,7 +267,7 @@ static struct comp_dev *src_new(struct sof_ipc_comp *comp) { struct comp_dev *dev; struct sof_ipc_comp_src *src;
- struct sof_ipc_comp_src *ipc_src = (struct sof_ipc_comp_src *)comp;
- struct sof_ipc_comp_src *ipc_src = (struct sof_ipc_comp_src *) comp; struct comp_data *cd; int i;
@@ -274,7 +278,7 @@ static struct comp_dev *src_new(struct sof_ipc_comp *comp) if (dev == NULL) return NULL;
- src = (struct sof_ipc_comp_src *)&dev->comp;
src = (struct sof_ipc_comp_src *) &dev->comp; memcpy(src, ipc_src, sizeof(struct sof_ipc_comp_src));
cd = rmalloc(RZONE_RUNTIME, RFLAGS_NONE, sizeof(*cd));
@@ -317,6 +321,7 @@ static int src_params(struct comp_dev *dev, struct stream_params *params) int32_t *buffer_start; int n = 0; struct comp_data *cd = comp_get_drvdata(dev);
struct sof_ipc_comp_src *src = (struct sof_ipc_comp_src *) &dev->comp;
trace_src("SPa");
@@ -325,23 +330,43 @@ static int src_params(struct comp_dev *dev, struct stream_params *params) || (params->pcm->frame_fmt != SOF_IPC_FRAME_S32_LE)) return -EINVAL;
- /* No data transformation */
- comp_set_sink_params(dev, params);
- /* Allocate needed memory for delay lines */ source = list_first_item(&dev->bsource_list, struct comp_buffer, sink_list); sink = list_first_item(&dev->bsink_list, struct comp_buffer, source_list);
- src_buffer_lengths(&need, source->params.pcm->rate,
sink->params.pcm->rate, source->params.pcm->channels);
/* Copy PCM stream parameters and the channel map array */
memcpy(&cd->pcm_params, &(*params->pcm),
sizeof(struct sof_ipc_pcm_params));
for (i = 0; i < params->pcm->channels; i++)
cd->pcm_params.channel_map[i] = params->pcm->channel_map[i];
/* Point sink stream parameters to copy */
sink->params.pcm = &cd->pcm_params;
/* Stored IPC from src_new() contains the output rate for sink,
* set the new rate for sink.
*/
sink->params.pcm->rate = src->out_rate;
/* Adjust sink buffer parameters to match fs_out/fs_in */
sink->params.pcm->period_count = sink->params.pcm->period_count
* sink->params.pcm->rate / source->params.pcm->rate;
sink->params.pcm->period_bytes = sink->params.pcm->period_bytes
* sink->params.pcm->rate / source->params.pcm->rate;
/* Allocate needed memory for delay lines */
if (src_buffer_lengths(&need, source->params.pcm->rate,
sink->params.pcm->rate, source->params.pcm->channels) < 0)
return -EINVAL;
delay_lines_size = sizeof(int32_t) * need.total; if (cd->delay_lines != NULL) rfree(cd->delay_lines);
cd->delay_lines = rmalloc(RZONE_RUNTIME, RFLAGS_NONE, delay_lines_size); if (cd->delay_lines == NULL)
return -EINVAL;
return -ENOMEM;
/* Clear all delay lines here */ memset(cd->delay_lines, 0, delay_lines_size);
@@ -369,19 +394,20 @@ static int src_params(struct comp_dev *dev, struct stream_params *params) */ trace_src("SFa"); cd->src_func = fallback_s32;
return(-EINVAL);
break;
rfree(cd->delay_lines);
return -EINVAL;
}
/* Check that src blk_in and blk_out are less than params.period_frames.
- Return an error if the period is too short.
*/
- if (src_polyphase_get_blk_in(&cd->src[0]) > source->params.pcm->period_count)
return(-EINVAL);
- if (src_polyphase_get_blk_out(&cd->src[0]) > sink->params.pcm->period_count)
return(-EINVAL);
if (src_polyphase_get_blk_in(&cd->src[0])
> source->params.pcm->period_count)
return -EINVAL;
if (src_polyphase_get_blk_out(&cd->src[0])
> sink->params.pcm->period_count)
return -EINVAL;
return 0;
} @@ -453,7 +479,8 @@ static int src_copy(struct comp_dev *dev) struct comp_buffer *sink; uint32_t frames_source; uint32_t frames_sink;
- int need_source, need_sink, min_frames;
int need_source, need_sink;
// int min_frames;
trace_comp("SRC");
@@ -464,25 +491,12 @@ static int src_copy(struct comp_dev *dev) source_list);
/* Check that source has enough frames available and sink enough
* frames free.
*/ frames_source = source->params.pcm->period_count; frames_sink = sink->params.pcm->period_count;* frames free. Increase tried period_count if not sufficient to run.
- min_frames = src_polyphase_get_blk_in(&cd->src[0]);
- if (frames_source > min_frames)
need_source = frames_source * source->params.pcm->frame_size;
- else {
frames_source = min_frames;
need_source = min_frames * source->params.pcm->frame_size;
- }
- min_frames = src_polyphase_get_blk_out(&cd->src[0]);
- if (frames_sink > min_frames)
need_sink = frames_sink * sink->params.pcm->frame_size;
- else {
frames_sink = min_frames;
need_sink = min_frames * sink->params.pcm->frame_size;
- }
need_source = source->params.pcm->period_bytes;
need_sink = sink->params.pcm->period_bytes;
/* Run as many times as buffers allow */ while ((source->avail >= need_source) && (sink->free >= need_sink)) {
diff --git a/src/include/reef/audio/buffer.h b/src/include/reef/audio/buffer.h index 5f2dbb7..0817a40 100644 --- a/src/include/reef/audio/buffer.h +++ b/src/include/reef/audio/buffer.h @@ -119,20 +119,20 @@ static inline void comp_update_sink_free_avail(struct comp_buffer *snk, int n) static inline void comp_wrap_source_r_ptr_circular(struct comp_buffer *src) { if (src->r_ptr >= src->end_addr)
src->r_ptr -= src->alloc_size;
src->r_ptr -= src->ipc_buffer.size; if (src->r_ptr < src->addr)
src->r_ptr += src->alloc_size;
src->r_ptr += src->ipc_buffer.size;
}
static inline void comp_wrap_sink_w_ptr_circular(struct comp_buffer *snk) { if (snk->w_ptr >= snk->end_addr)
snk->w_ptr -= snk->alloc_size;
snk->w_ptr -= snk->ipc_buffer.size; if (snk->w_ptr < snk->addr)
snk->w_ptr += snk->alloc_size;
snk->w_ptr += snk->ipc_buffer.size;
}
#endif diff --git a/src/include/uapi/ipc.h b/src/include/uapi/ipc.h index 3d78db3..d89039e 100644 --- a/src/include/uapi/ipc.h +++ b/src/include/uapi/ipc.h @@ -488,6 +488,7 @@ struct sof_ipc_comp_src { struct sof_ipc_pcm_comp pcm; uint32_t in_mask; /* SOF_RATE_ supported input rates */ uint32_t out_mask; /* SOF_RATE_ supported output rates */
- int32_t out_rate;
} __attribute__((packed));
/* generic MUX component */
--------------------------------------------------------------------- Intel Corporation (UK) Limited Registered No. 1134945 (England) Registered Office: Pipers Way, Swindon SN3 1RJ VAT No: 860 2173 47
This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). Any review or distribution by others is strictly prohibited. If you are not the intended recipient, please contact the sender and delete all copies.