[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