#include "sound/compress_offload.h"
#include "tinycompress.h"
+/*
+ * struct compress_ops:
+ * ops structure containing ops corresponding to exposed
+ * compress APIs, needs to be implemented by plugin lib for
+ * virtual compress nodes. Real compress node handling is
+ * done in compress_hw.c
+ */
struct compress_ops {
- void *(*open)(unsigned int card, unsigned int device,
+ void *(*open_by_name)(const char *name,
unsigned int flags, struct compr_config *config);
void (*close)(void *compress_data);
int (*get_hpointer)(void *compress_data,
void (*set_max_poll_wait)(void *compress_data, int milliseconds);
void (*set_nonblock)(void *compress_data, int nonblock);
int (*wait)(void *compress_data, int timeout_ms);
- bool (*is_codec_supported)(unsigned int card, unsigned int device,
+ bool (*is_codec_supported_by_name) (const char *name,
unsigned int flags, struct snd_codec *codec);
int (*is_compress_running)(void *compress_data);
int (*is_compress_ready)(void *compress_data);
struct compress *compress_open(unsigned int card, unsigned int device,
unsigned int flags, struct compr_config *config);
+/*
+ * compress_open_by_name: open a new compress stream
+ * returns the valid struct compress on success, NULL on failure
+ * If config does not specify a requested fragment size, on return
+ * it will be updated with the size and number of fragments that
+ * were configured.
+ * format of name is :
+ * hw:<card>,<device> for real hw compress node
+ * <plugin_libname>:<custom string> for virtual compress node
+ *
+ * @name: name of the compress node
+ * @flags: device flags can be COMPRESS_OUT or COMPRESS_IN
+ * @config: stream config requested. Returns actual fragment config
+ */
+
+struct compress *compress_open_by_name(const char *name,
+ unsigned int flags, struct compr_config *config);
/*
* compress_close: close the compress stream
*
bool is_codec_supported(unsigned int card, unsigned int device,
unsigned int flags, struct snd_codec *codec);
+/*
+ * is_codec_supported_by_name:check if the given codec is supported
+ * returns true when supported, false if not.
+ * format of name is :
+ * hw:<card>,<device> for real hw compress node
+ * <plugin_libname>:<custom string> for virtual compress node
+ *
+ * @name: name of the compress node
+ * @flags: stream flags
+ * @codec: codec type and parameters to be checked
+ */
+bool is_codec_supported_by_name(const char *name,
+ unsigned int flags, struct snd_codec *codec);
+
/*
* compress_set_max_poll_wait: set the maximum time tinycompress
* will wait for driver to signal a poll(). Interval is in
tinycompress_LTLIBRARIES = libtinycompress.la
libtinycompress_la_SOURCES = compress.c compress_hw.c
libtinycompress_la_CFLAGS = -I$(top_srcdir)/include
+libtinycompress_la_LIBADD = -ldl
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#include <dlfcn.h>
+#include <stdio.h>
+#include <string.h>
#include <sys/time.h>
#include "tinycompress/tinycompress.h"
#include "tinycompress/compress_ops.h"
+#ifndef TINYCOMPRESS_PLUGIN_DIR
+#define TINYCOMPRESS_PLUGIN_DIR "/usr/lib/tinycompress-lib/"
+#endif
+
struct compress {
struct compress_ops *ops;
void *data;
+ void *dl_hdl;
};
extern struct compress_ops compress_hw_ops;
unsigned int flags, struct compr_config *config)
{
struct compress *compress;
+ char name[128];
+ snprintf(name, sizeof(name), "hw:%u,%u", card, device);
compress = calloc(1, sizeof(struct compress));
if (!compress)
return NULL;
compress->ops = &compress_hw_ops;
- compress->data = compress->ops->open(card, device, flags, config);
+ compress->data = compress->ops->open_by_name(name, flags, config);
+ if (compress->data == NULL) {
+ free(compress);
+ return NULL;
+ }
+ return compress;
+}
+
+static int populate_compress_plugin_ops(struct compress *compress, const char *name)
+{
+ unsigned int ret = -1;
+ char *token, *token_saveptr;
+ char *compr_name;
+ char lib_name[128];
+ void *dl_hdl;
+ const char *err = NULL;
+
+ token = strdup(name);
+ compr_name = strtok_r(token, ":", &token_saveptr);
+
+ snprintf(lib_name, sizeof(lib_name), "%slibtinycompress_module_%s.so", TINYCOMPRESS_PLUGIN_DIR, compr_name);
+
+ free(token);
+ dl_hdl = dlopen(lib_name, RTLD_NOW);
+ if (!dl_hdl) {
+ fprintf(stderr, "%s: unable to open %s, error: %s\n",
+ __func__, lib_name, dlerror());
+ return ret;
+ }
+
+ compress->ops = dlsym(dl_hdl, "compress_plugin_ops");
+ err = dlerror();
+ if (err) {
+ fprintf(stderr, "%s: dlsym to ops failed, err = '%s'\n",
+ __func__, err);
+ dlclose(dl_hdl);
+ return ret;
+ }
+ compress->dl_hdl = dl_hdl;
+ return 0;
+}
+
+/*
+ * Format of name is :
+ * 'hw:<card>,<device>'for hw compress nodes and
+ * '<plugin_name>:<custom_data>' for virtual compress nodes.
+ * It dynamically loads the plugin library whose name is
+ * libtinycompress_module_<plugin_name>.so. Plugin library
+ * needs to implement/expose compress_plugin_ops.
+ */
+struct compress *compress_open_by_name(const char *name,
+ unsigned int flags, struct compr_config *config)
+{
+ struct compress *compress;
+
+ compress = calloc(1, sizeof(struct compress));
+ if (!compress)
+ return NULL;
+
+ if ((name[0] == 'h') || (name[1] == 'w') || (name[2] == ':')) {
+ compress->ops = &compress_hw_ops;
+ } else {
+ if (populate_compress_plugin_ops(compress, name)) {
+ free(compress);
+ return NULL;
+ }
+ }
+
+ compress->data = compress->ops->open_by_name(name, flags, config);
if (compress->data == NULL) {
+ if (compress->dl_hdl)
+ dlclose(compress->dl_hdl);
free(compress);
return NULL;
}
void compress_close(struct compress *compress)
{
compress->ops->close(compress->data);
+ if (compress->dl_hdl)
+ dlclose(compress->dl_hdl);
+
free(compress);
}
unsigned int flags, struct snd_codec *codec)
{
struct compress_ops *ops = &compress_hw_ops;
+ char name[128];
+
+ snprintf(name, sizeof(name), "hw:%u,%u", card, device);
+
+ return ops->is_codec_supported_by_name(name, flags, codec);
+}
+
+bool is_codec_supported_by_name(const char *name,
+ unsigned int flags, struct snd_codec *codec)
+{
+ struct compress *compress;
+ bool ret;
+
+ compress = calloc(1, sizeof(struct compress));
+ if (!compress)
+ return false;
+
+ if ((name[0] == 'h') || (name[1] == 'w') || (name[2] == ':')) {
+ compress->ops = &compress_hw_ops;
+ } else {
+ if (populate_compress_plugin_ops(compress, name)) {
+ free(compress);
+ return NULL;
+ }
+ }
+
+ ret = compress->ops->is_codec_supported_by_name(name, flags, codec);
+
+ if (compress->dl_hdl)
+ dlclose(compress->dl_hdl);
+ free(compress);
- return ops->is_codec_supported(card, device, flags, codec);
+ return ret;
}
void compress_set_max_poll_wait(struct compress *compress, int milliseconds)
memcpy(¶ms->codec, config->codec, sizeof(params->codec));
}
-static void *compress_hw_open(unsigned int card, unsigned int device,
+static void *compress_hw_open_by_name(const char *name,
unsigned int flags, struct compr_config *config)
{
struct compress_hw_data *compress;
struct snd_compr_params params;
struct snd_compr_caps caps;
+ unsigned int card, device;
char fn[256];
if (!config) {
return &bad_compress;
}
+ if (sscanf(&name[3], "%u,%u", &card, &device) != 2) {
+ oops(&bad_compress, errno, "Invalid device name %s", name);
+ return &bad_compress;
+ }
+
compress = calloc(1, sizeof(struct compress_hw_data));
if (!compress) {
oops(&bad_compress, errno, "cannot allocate compress object");
return 0;
}
-static bool compress_hw_is_codec_supported(unsigned int card, unsigned int device,
+static bool compress_hw_is_codec_supported_by_name(const char *name,
unsigned int flags, struct snd_codec *codec)
{
+ unsigned int card, device;
unsigned int dev_flag;
bool ret;
int fd;
char fn[256];
+ if (sscanf(&name[3], "%u,%u", &card, &device) != 2)
+ return false;
+
snprintf(fn, sizeof(fn), "/dev/snd/comprC%uD%u", card, device);
if (flags & COMPRESS_OUT)
}
struct compress_ops compress_hw_ops = {
- .open = compress_hw_open,
+ .open_by_name = compress_hw_open_by_name,
.close = compress_hw_close,
.get_hpointer = compress_hw_get_hpointer,
.get_tstamp = compress_hw_get_tstamp,
.set_max_poll_wait = compress_hw_set_max_poll_wait,
.set_nonblock = compress_hw_set_nonblock,
.wait = compress_hw_wait,
- .is_codec_supported = compress_hw_is_codec_supported,
+ .is_codec_supported_by_name = compress_hw_is_codec_supported_by_name,
.is_compress_running = is_compress_hw_running,
.is_compress_ready = is_compress_hw_ready,
.get_error = compress_hw_get_error,