From: Rohit kumar Date: Tue, 22 Sep 2020 11:52:05 +0000 (+0530) Subject: src: lib: compress: Add support for plugins X-Git-Tag: v1.2.4~3^2 X-Git-Url: https://git.alsa-project.org/?a=commitdiff_plain;h=cffaaf90993d94ce1f91bedac535bd869b9fd21f;p=tinycompress.git src: lib: compress: Add support for plugins Add compress_open_by_name() and is_codec_supported_by_name() to support plugins. Format of name is 'hw:,' for hw compress nodes and ':' for virtual compress nodes. It dynamically loads the plugin library whose name is libtinycompress_module_.so. Plugin library needs to expose compress_plugin_ops. Default path of plugin lib is /usr/lib/tinycompress-lib/ and it can be updated by defining TINYCOMPRESS_PLUGIN_DIR in makefile. Signed-off-by: Rohit kumar --- diff --git a/include/tinycompress/compress_ops.h b/include/tinycompress/compress_ops.h index 58bb433..9b204a6 100644 --- a/include/tinycompress/compress_ops.h +++ b/include/tinycompress/compress_ops.h @@ -8,8 +8,15 @@ #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, @@ -30,7 +37,7 @@ struct compress_ops { 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); diff --git a/include/tinycompress/tinycompress.h b/include/tinycompress/tinycompress.h index f0fae30..c710a61 100644 --- a/include/tinycompress/tinycompress.h +++ b/include/tinycompress/tinycompress.h @@ -103,6 +103,23 @@ struct snd_compr_tstamp; 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:, for real hw compress node + * : 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 * @@ -253,6 +270,20 @@ int compress_set_gapless_metadata(struct compress *compress, 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:, for real hw compress node + * : 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 diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index db7ee27..0df177f 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -3,3 +3,4 @@ tinycompressdir = $(libdir) tinycompress_LTLIBRARIES = libtinycompress.la libtinycompress_la_SOURCES = compress.c compress_hw.c libtinycompress_la_CFLAGS = -I$(top_srcdir)/include +libtinycompress_la_LIBADD = -ldl diff --git a/src/lib/compress.c b/src/lib/compress.c index b473a00..f273744 100644 --- a/src/lib/compress.c +++ b/src/lib/compress.c @@ -55,13 +55,21 @@ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ +#include +#include +#include #include #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; @@ -85,14 +93,86 @@ struct compress *compress_open(unsigned int card, unsigned int device, 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:,'for hw compress nodes and + * ':' for virtual compress nodes. + * It dynamically loads the plugin library whose name is + * libtinycompress_module_.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; } @@ -102,6 +182,9 @@ struct compress *compress_open(unsigned int card, unsigned int device, void compress_close(struct compress *compress) { compress->ops->close(compress->data); + if (compress->dl_hdl) + dlclose(compress->dl_hdl); + free(compress); } @@ -172,8 +255,39 @@ bool is_codec_supported(unsigned int card, unsigned int device, 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) diff --git a/src/lib/compress_hw.c b/src/lib/compress_hw.c index a09bc18..9944f0e 100644 --- a/src/lib/compress_hw.c +++ b/src/lib/compress_hw.c @@ -127,12 +127,13 @@ fill_compress_hw_params(struct compr_config *config, struct snd_compr_params *pa 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) { @@ -140,6 +141,11 @@ static void *compress_hw_open(unsigned int card, unsigned int device, 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"); @@ -500,14 +506,18 @@ static int compress_hw_set_gapless_metadata(void *data, 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) @@ -564,7 +574,7 @@ static int compress_hw_wait(void *data, int timeout_ms) } 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, @@ -581,7 +591,7 @@ struct compress_ops compress_hw_ops = { .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,