[alsa-devel] [PATCH] tinycompress: add gapless meta data APIs
Vinod Koul
vinod.koul at intel.com
Fri Feb 22 10:52:40 CET 2013
Based on newly introduced kernel API, we add gapless metatdata to the library.
Since kernel can recieve only key/value pairs for metadata we add a structure for
gapless_metdata and handle this in library
Signed-off-by: Vinod Koul <vinod.koul at intel.com>
---
compress.c | 71 +++++++++++++++++++++++++++++++++++
include/sound/compress_offload.h | 18 ++++++++-
include/tinycompress/tinycompress.h | 37 ++++++++++++++++++
include/tinycompress/version.h | 4 +-
4 files changed, 126 insertions(+), 4 deletions(-)
diff --git a/compress.c b/compress.c
index d44d5fe..5b600c3 100644
--- a/compress.c
+++ b/compress.c
@@ -85,6 +85,8 @@ struct compress {
char error[COMPR_ERR_MAX];
struct compr_config *config;
unsigned int running:1;
+ unsigned int gapless_metadata;
+ unsigned int next_track;
};
static int oops(struct compress *compress, int e, const char *fmt, ...)
@@ -121,6 +123,17 @@ int is_compress_ready(struct compress *compress)
return (compress->fd > 0) ? 1 : 0;
}
+static int get_compress_version(struct compress *compress)
+{
+ int version = 0;
+
+ if (ioctl(compress->fd, SNDRV_COMPRESS_IOCTL_VERSION, &version)) {
+ oops(compress, errno, "cant read version");
+ return -1;
+ }
+ return version;
+}
+
static bool _is_codec_supported(struct compress *compress, struct compr_config *config)
{
struct snd_compr_caps caps;
@@ -212,6 +225,8 @@ struct compress *compress_open(unsigned int card, unsigned int device,
return &bad_compress;
}
+ compress->next_track = 0;
+ compress->gapless_metadata = 0;
compress->config = calloc(1, sizeof(*config));
if (!compress->config)
goto input_fail;
@@ -401,6 +416,62 @@ int compress_drain(struct compress *compress)
return 0;
}
+int compress_partial_drain(struct compress *compress)
+{
+ if (!is_compress_running(compress))
+ return oops(compress, -ENODEV, "device not ready");
+
+ if (!compress->next_track)
+ return oops(compress, -EPERM, "next track not signalled");
+ if (ioctl(compress->fd, SNDRV_COMPRESS_PARTIAL_DRAIN))
+ return oops(compress, errno, "cannot drain the stream\n");
+ compress->next_track = 0;
+ return 0;
+}
+
+int compress_next_track(struct compress *compress)
+{
+ if (!is_compress_running(compress))
+ return oops(compress, -ENODEV, "device not ready");
+
+ if (!compress->gapless_metadata)
+ return oops(compress, -EPERM, "metadata not set");
+ if (ioctl(compress->fd, SNDRV_COMPRESS_NEXT_TRACK))
+ return oops(compress, errno, "cannot set next track\n");
+ compress->next_track = 1;
+ compress->gapless_metadata = 0;
+ return 0;
+}
+
+int compress_set_gapless_metadata(struct compress *compress,
+ struct compr_gapless_mdata *mdata)
+{
+ struct snd_compr_metadata metadata;
+ int version;
+
+ if (!is_compress_ready(compress))
+ return oops(compress, -ENODEV, "device not ready");
+
+ version = get_compress_version(compress);
+ if (version <= 0)
+ return -1;
+
+ if (version < SNDRV_PROTOCOL_VERSION(0, 1, 1))
+ return oops(compress, -ENXIO, "gapless apis not supported in kernel");
+
+ metadata.key = SNDRV_COMPRESS_ENCODER_PADDING;
+ metadata.value[0] = mdata->encoder_padding;
+ if (ioctl(compress->fd, SNDRV_COMPRESS_SET_METADATA, &metadata))
+ return oops(compress, errno, "can't set metadata for stream\n");
+
+ metadata.key = SNDRV_COMPRESS_ENCODER_DELAY;
+ metadata.value[0] = mdata->encoder_delay;
+ if (ioctl(compress->fd, SNDRV_COMPRESS_SET_METADATA, &metadata))
+ return oops(compress, errno, "can't set metadata for stream\n");
+ compress->gapless_metadata = 1;
+ return 0;
+}
+
bool is_codec_supported(unsigned int card, unsigned int device,
unsigned int flags, struct snd_codec *codec)
{
diff --git a/include/sound/compress_offload.h b/include/sound/compress_offload.h
index bbb09bc..17377df 100644
--- a/include/sound/compress_offload.h
+++ b/include/sound/compress_offload.h
@@ -16,7 +16,7 @@
#include <sound/asound.h>
//#include <sound/compress_params.h>
-#define SNDRV_COMPRESS_VERSION SNDRV_PROTOCOL_VERSION(0, 1, 0)
+#define SNDRV_COMPRESS_VERSION SNDRV_PROTOCOL_VERSION(0, 1, 1)
struct snd_compressed_buffer {
__u32 fragment_size;
@@ -64,11 +64,23 @@ struct snd_compr_codec_caps {
struct snd_codec_desc descriptor[MAX_NUM_CODEC_DESCRIPTORS];
};
+enum {
+ SNDRV_COMPRESS_ENCODER_PADDING = 1,
+ SNDRV_COMPRESS_ENCODER_DELAY = 2,
+};
+
+struct snd_compr_metadata {
+ __u32 key;
+ __u32 value[8];
+};
+
#define SNDRV_COMPRESS_IOCTL_VERSION _IOR('C', 0x00, int)
#define SNDRV_COMPRESS_GET_CAPS _IOWR('C', 0x10, struct snd_compr_caps)
#define SNDRV_COMPRESS_GET_CODEC_CAPS _IOWR('C', 0x11, struct snd_compr_codec_caps)
#define SNDRV_COMPRESS_SET_PARAMS _IOW('C', 0x12, struct snd_compr_params)
#define SNDRV_COMPRESS_GET_PARAMS _IOR('C', 0x13, struct snd_codec)
+#define SNDRV_COMPRESS_SET_METADATA _IOW('C', 0x14, struct snd_compr_metadata)
+#define SNDRV_COMPRESS_GET_METADATA _IOWR('C', 0x15, struct snd_compr_metadata)
#define SNDRV_COMPRESS_TSTAMP _IOR('C', 0x20, struct snd_compr_tstamp)
#define SNDRV_COMPRESS_AVAIL _IOR('C', 0x21, struct snd_compr_avail)
#define SNDRV_COMPRESS_PAUSE _IO('C', 0x30)
@@ -76,6 +88,8 @@ struct snd_compr_codec_caps {
#define SNDRV_COMPRESS_START _IO('C', 0x32)
#define SNDRV_COMPRESS_STOP _IO('C', 0x33)
#define SNDRV_COMPRESS_DRAIN _IO('C', 0x34)
-
+#define SNDRV_COMPRESS_NEXT_TRACK _IO('C', 0x35)
+#define SNDRV_COMPRESS_PARTIAL_DRAIN _IO('C', 0x36)
#define SND_COMPR_TRIGGER_DRAIN 7
+#define SND_COMPR_TRIGGER_PARTIAL_DRAIN 8
#endif
diff --git a/include/tinycompress/tinycompress.h b/include/tinycompress/tinycompress.h
index 13dea3e..e129817 100644
--- a/include/tinycompress/tinycompress.h
+++ b/include/tinycompress/tinycompress.h
@@ -69,6 +69,11 @@ struct compr_config {
struct snd_codec *codec;
};
+struct compr_gapless_mdata {
+ __u32 encoder_delay;
+ __u32 encoder_padding;
+};
+
#define COMPRESS_OUT 0x00000000
#define COMPRESS_IN 0x10000000
@@ -165,6 +170,38 @@ int compress_resume(struct compress *compress);
int compress_drain(struct compress *compress);
/*
+ * compress_next_track: set the next track for stream
+ *
+ * return 0 on success, negative on error
+ *
+ * @compress: compress stream to be transistioned to next track
+ */
+int compress_next_track(struct compress *compress);
+
+/*
+ * compress_partial_drain: drain will return after the last frame is decoded
+ * by DSP and will play the , All the data written into compressed
+ * ring buffer is decoded
+ *
+ * return 0 on success, negative on error
+ *
+ * @compress: compress stream to be drain
+ */
+int compress_partial_drain(struct compress *compress);
+
+/*
+ * compress_set_gapless_metadata: set gapless metadata of a compress strem
+ *
+ * return 0 on success, negative on error
+ *
+ * @compress: compress stream for which metadata has to set
+ * @mdata: metadata encoder delay and padding
+ */
+
+int compress_set_gapless_metadata(struct compress *compress,
+ struct compr_gapless_mdata *mdata);
+
+/*
* is_codec_supported:check if the given codec is supported
* returns true when supported, false if not
*
diff --git a/include/tinycompress/version.h b/include/tinycompress/version.h
index 89f0f4e..db191d6 100644
--- a/include/tinycompress/version.h
+++ b/include/tinycompress/version.h
@@ -56,7 +56,7 @@
#define TINYCOMPRESS_LIB_MAJOR 0 /* major number of library version */
#define TINYCOMPRESS_LIB_MINOR 0 /* minor number of library version */
-#define TINYCOMPRESS_LIB_SUBMINOR 1 /* subminor number of library version */
+#define TINYCOMPRESS_LIB_SUBMINOR 2 /* subminor number of library version */
/** library version */
#define TINYCOMPRESS_LIB_VERSION \
@@ -65,6 +65,6 @@
TINYCOMPRESS_LIB_SUBMINOR)
/** library version (string) */
-#define TINYCOMPRESS_LIB_VERSION_STR "0.0.1"
+#define TINYCOMPRESS_LIB_VERSION_STR "0.0.2"
#endif
--
1.7.0.4
More information about the Alsa-devel
mailing list