[Sound-open-firmware] [PATCH v2 2/2] Passthrough component added
Ranjani Sridharan
ranjani.sridharan at linux.intel.com
Tue Sep 5 17:21:36 CEST 2017
This patch adds a passthrough component that copies the input stream
from the source buffer to the sink buffer. It is meant to serve as a
template for creating new components.
Signed-off-by: Ranjani Sridharan <ranjani.sridharan at linux.intel.com>
---
src/audio/Makefile.am | 3 +-
src/audio/passthrough.c | 238 +++++++++++++++++++++++++++++++++++++++++++++++
src/include/reef/trace.h | 1 +
src/include/uapi/ipc.h | 7 ++
4 files changed, 248 insertions(+), 1 deletion(-)
create mode 100644 src/audio/passthrough.c
diff --git a/src/audio/Makefile.am b/src/audio/Makefile.am
index 285422e..c71430c 100644
--- a/src/audio/Makefile.am
+++ b/src/audio/Makefile.am
@@ -17,7 +17,8 @@ libaudio_a_SOURCES = \
pipeline.c \
pipeline_static.c \
component.c \
- buffer.c
+ buffer.c \
+ passthrough.c
libaudio_a_CFLAGS = \
$(ARCH_CFLAGS) \
diff --git a/src/audio/passthrough.c b/src/audio/passthrough.c
new file mode 100644
index 0000000..4163db9
--- /dev/null
+++ b/src/audio/passthrough.c
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2016, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Intel Corporation nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: Ranjani Sridharan <ranjani.sridharan at linux.intel.com>
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <reef/lock.h>
+#include <reef/alloc.h>
+#include <reef/list.h>
+#include <reef/stream.h>
+#include <reef/trace.h>
+#include <reef/audio/component.h>
+#include <reef/audio/pipeline.h>
+#include <uapi/ipc.h>
+
+/* tracing */
+#define trace_pass(__e) trace_event(TRACE_CLASS_PASS, __e)
+#define trace_pass_error(__e) trace_error(TRACE_CLASS_PASS, __e)
+#define tracev_pass(__e) tracev_event(TRACE_CLASS_PASS, __e)
+
+/* The passthrough component, as the name inplies, allows the source buffer
+ * to pass through the component, without any processing, to the sink buffer.
+ * It supports 16-bits and 32-bits data formats.
+ * This code is intended to be used as a template for creating new components.
+ */
+
+/*
+ * passthrough_comp_data structure: This is private data that cannot be touched
+ * outside the component. It contains:
+ * passthrough_func - function that performs the buffer copy
+ */
+struct passthrough_comp_data {
+ int (*passthrough_func)(struct comp_dev *dev, struct comp_buffer *sink,
+ struct comp_buffer *source, uint32_t frames);
+
+};
+
+/* This function performs memcpy of the stream data from the source buffer to
+ * the sink buffer. It returns the number of frames that were copied.
+ */
+static int passthrough_function(struct comp_dev *dev,
+ struct comp_buffer *sink_buffer,
+ struct comp_buffer *source_buffer, uint32_t frames)
+{
+ struct sof_ipc_comp_config *config = COMP_GET_CONFIG(dev);
+ int32_t *src = (int32_t *) source_buffer->r_ptr;
+ int32_t *dest = (int32_t *) sink_buffer->w_ptr;
+ int nch = dev->params.channels;
+
+ /* copy frames from source to destination */
+ switch (config->frame_fmt) {
+ case SOF_IPC_FRAME_S16_LE:
+ memcpy(dest, src, frames * nch * sizeof(int16_t));
+ break;
+ case SOF_IPC_FRAME_S32_LE:
+ case SOF_IPC_FRAME_S24_4LE:
+ case SOF_IPC_FRAME_FLOAT:
+ memcpy(dest, src, frames * nch * sizeof(int32_t));
+ break;
+ default:
+ trace_pass_error("PTp");
+ return -EINVAL;
+ }
+
+ return frames;
+}
+
+/* passthrough_new create the new passthrough component and allocates
+ * memory for the component and its private data.
+ * It returns a pointer to struct comp_dev that was created.
+ */
+static struct comp_dev *passthrough_new(struct sof_ipc_comp *comp)
+{
+ struct comp_dev *dev;
+ struct passthrough_comp_data *cd;
+
+ trace_pass("PTn");
+ dev = rzalloc(RZONE_RUNTIME, RFLAGS_NONE,
+ COMP_SIZE(struct sof_ipc_comp_passthrough));
+ if (dev == NULL)
+ return NULL;
+
+ memcpy(&dev->comp, comp, sizeof(struct sof_ipc_comp_passthrough));
+
+ cd = rzalloc(RZONE_RUNTIME, RFLAGS_NONE, sizeof(*cd));
+ if (cd == NULL) {
+ rfree(dev);
+ return NULL;
+ }
+
+ comp_set_drvdata(dev, cd);
+ cd->passthrough_func = passthrough_function;
+
+ return dev;
+}
+
+/* passthrough_free performs the clean-up */
+static void passthrough_free(struct comp_dev *dev)
+{
+ struct passthrough_comp_data *cd = comp_get_drvdata(dev);
+
+ rfree(cd);
+ rfree(dev);
+}
+
+/* passthrough_params sets the component audio stream parameters */
+static int passthrough_params(struct comp_dev *dev)
+{
+ return 0;
+}
+
+/* passthrough_cmd is used to pass standard and bespoke commands (with data)
+ * to the component
+ */
+static int passthrough_cmd(struct comp_dev *dev, int cmd, void *data)
+{
+ int ret = 0;
+
+ switch (cmd) {
+ case COMP_CMD_START:
+ case COMP_CMD_STOP:
+ case COMP_CMD_PAUSE:
+ case COMP_CMD_RELEASE:
+ default:
+ ret = comp_set_state(dev, cmd);
+ break;
+ }
+
+ return ret;
+}
+
+/* passthrough_copy is called when stream data flows through the pipeline
+ * It calls passthrough_function to copy the source buffer to the sink buffer.
+ * It returns the number of frames that were copied.
+ */
+static int passthrough_copy(struct comp_dev *dev)
+{
+ struct passthrough_comp_data *cd = comp_get_drvdata(dev);
+ struct comp_buffer *source_buffer = NULL, *sink_buffer = NULL;
+ uint32_t copy_bytes;
+
+ /* get source and sink buffers */
+ source_buffer = list_first_item(&dev->bsource_list, struct comp_buffer,
+ sink_list);
+ sink_buffer = list_first_item(&dev->bsink_list, struct comp_buffer,
+ source_list);
+
+ /* check that source has enough frames available and sink enough
+ * frames free
+ */
+ copy_bytes = comp_buffer_get_copy_bytes(dev, source_buffer,
+ sink_buffer);
+
+ if (copy_bytes < dev->frames * dev->frame_bytes) {
+ trace_pass_error("PTc");
+ return -EINVAL;
+ }
+
+ /* Run passthrough if buffers have enough room */
+ cd->passthrough_func(dev, sink_buffer, source_buffer, dev->frames);
+
+ comp_update_buffer_consume(source_buffer,
+ dev->params.host_period_bytes);
+ comp_update_buffer_produce(sink_buffer, dev->params.host_period_bytes);
+
+ return dev->frames;
+}
+
+/* passthrough_preload is used for preloading the component buffers before
+ * pipeline start
+ */
+static int passthrough_preload(struct comp_dev *dev)
+{
+ return passthrough_copy(dev);
+}
+
+/* passthrough_reset rests the component state */
+static int passthrough_reset(struct comp_dev *dev)
+{
+ trace_pass("PTe");
+ dev->state = COMP_STATE_INIT;
+ return 0;
+}
+
+/* passthrough_prepare prepares the component for receiving stream data */
+static int passthrough_prepare(struct comp_dev *dev)
+{
+ trace_pass("PTl");
+ dev->state = COMP_STATE_PREPARE;
+ return 0;
+}
+
+/* passthrough component driver ops */
+struct comp_driver comp_passthrough = {
+ .type = SOF_COMP_PASSTHROUGH,
+ .ops = {
+ .new = passthrough_new,
+ .free = passthrough_free,
+ .params = passthrough_params,
+ .cmd = passthrough_cmd,
+ .copy = passthrough_copy,
+ .prepare = passthrough_prepare,
+ .reset = passthrough_reset,
+ .preload = passthrough_preload,
+ },
+};
+
+void sys_comp_passthrough_init(void)
+{
+ comp_register(&comp_passthrough);
+}
diff --git a/src/include/reef/trace.h b/src/include/reef/trace.h
index 300e8d8..b7ec31a 100644
--- a/src/include/reef/trace.h
+++ b/src/include/reef/trace.h
@@ -87,6 +87,7 @@
#define TRACE_CLASS_TONE (18 << 24)
#define TRACE_CLASS_EQ_FIR (19 << 24)
#define TRACE_CLASS_EQ_IIR (20 << 24)
+#define TRACE_CLASS_PASS (21 << 24)
/* move to config.h */
#define TRACE 1
diff --git a/src/include/uapi/ipc.h b/src/include/uapi/ipc.h
index be4c9f2..127ecf1 100644
--- a/src/include/uapi/ipc.h
+++ b/src/include/uapi/ipc.h
@@ -516,6 +516,7 @@ enum sof_comp_type {
SOF_COMP_EQ_FIR,
SOF_COMP_FILEREAD, /* host test based file IO */
SOF_COMP_FILEWRITE, /* host test based file IO */
+ SOF_COMP_PASSTHROUGH,
};
/* XRUN action for component */
@@ -615,6 +616,12 @@ struct sof_ipc_comp_mux {
struct sof_ipc_comp_config config;
} __attribute__((packed));
+/* generic passthrough component */
+struct sof_ipc_comp_passthrough {
+ struct sof_ipc_comp comp;
+ struct sof_ipc_comp_config config;
+} __attribute__((packed));
+
/* generic tone generator component */
struct sof_ipc_comp_tone {
struct sof_ipc_comp comp;
--
2.9.3
More information about the Sound-open-firmware
mailing list