]> git.alsa-project.org Git - tinycompress.git/commitdiff
src: lib: compress: Add support for plugins
authorRohit kumar <rohitkr@codeaurora.org>
Tue, 22 Sep 2020 11:52:05 +0000 (17:22 +0530)
committerRohit kumar <rohitkr@codeaurora.org>
Thu, 15 Oct 2020 06:43:28 +0000 (12:13 +0530)
Add compress_open_by_name() and is_codec_supported_by_name()
to support plugins. 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 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 <rohitkr@codeaurora.org>
include/tinycompress/compress_ops.h
include/tinycompress/tinycompress.h
src/lib/Makefile.am
src/lib/compress.c
src/lib/compress_hw.c

index 58bb4336bd2f64dc5588387f9449f0faf8a58953..9b204a6e7680699fc7204e1e8bb0d73f8cb5a26b 100644 (file)
@@ -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);
index f0fae30540623332336ddfb4f4b18e2c334603d4..c710a6198d7ebc2984ab8dc8a9eacc471a7346a1 100644 (file)
@@ -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:<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
  *
@@ -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:<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
index db7ee276b894c2539ec46b94dfe80e0e8275114e..0df177fe0643710833ccb70e1881d368778c1285 100644 (file)
@@ -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
index b473a00a18b5c9b66e166b7f80c22893a6b6db26..f27374455f19cc1fe370fc0500c1c23c361769a6 100644 (file)
  * 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;
@@ -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:<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;
        }
@@ -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)
index a09bc1834cf618ffd98bc9bb73b9160518afa5ab..9944f0e1a333798aa20abbb311a7640d84736451 100644 (file)
@@ -127,12 +127,13 @@ fill_compress_hw_params(struct compr_config *config, struct snd_compr_params *pa
        memcpy(&params->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,