From ad70adf4ddbacdb1206dabf81941fab746f71f39 Mon Sep 17 00:00:00 2001 From: Jeffy Chen Date: Tue, 14 Dec 2021 17:09:52 +0800 Subject: [PATCH 8/8] Support builtin v4l plugins Use --enable-builtin-plugins to enable it. Only support mplane plugin for now. Signed-off-by: Jeffy Chen --- configure.ac | 13 ++++++ lib/Makefile.am | 4 +- lib/libv4l-mplane/Makefile.am | 9 ++++ lib/libv4l-mplane/libv4l-mplane.c | 4 ++ lib/libv4l2/Makefile.am | 3 ++ lib/libv4l2/libv4l2-priv.h | 16 +++---- lib/libv4l2/libv4l2.c | 73 +++++++++++++++++++++++++++++++ lib/libv4l2/v4l2-plugin.c | 8 ++-- 8 files changed, 116 insertions(+), 14 deletions(-) diff --git a/configure.ac b/configure.ac index 3bb1d2a5..fdbcfd3f 100644 --- a/configure.ac +++ b/configure.ac @@ -524,6 +524,14 @@ AC_ARG_ENABLE(bpf, esac] ) +AC_ARG_ENABLE(builtin-plugins, + AS_HELP_STRING([--enable-builtin-plugins], [enable builtin libv4l plugins]), + [case "${enableval}" in + yes | no ) ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-builtin-plugins) ;; + esac] +) + PKG_CHECK_MODULES([SDL2], [sdl2 SDL2_image], [sdl_pc=yes], [sdl_pc=no]) AM_CONDITIONAL([HAVE_SDL], [test x$sdl_pc = xyes]) @@ -540,6 +548,7 @@ AM_CONDITIONAL([WITH_V4LUTILS], [test x$enable_v4l_utils != xno -a x$linux_o AM_CONDITIONAL([WITH_QV4L2], [test x${qt_pkgconfig} = xtrue -a x$enable_qv4l2 != xno]) AM_CONDITIONAL([WITH_QVIDCAP], [test x${qt_desktop_opengl} = xyes -a x$enable_qvidcap != xno]) AM_CONDITIONAL([WITH_V4L_PLUGINS], [test x$enable_dyn_libv4l != xno -a x$enable_shared != xno]) +AM_CONDITIONAL([WITH_V4L_BUILTIN_PLUGINS], [test x$enable_builtin_plugins = xyes]) AM_CONDITIONAL([WITH_V4L_WRAPPERS], [test x$enable_dyn_libv4l != xno -a x$enable_shared != xno]) AM_CONDITIONAL([WITH_QTGL], [test x${qt_desktop_opengl} = xyes]) AM_CONDITIONAL([WITH_GCONV], [test x$enable_gconv = xyes -a x$enable_shared = xyes -a x$with_gconvdir != x -a -f $with_gconvdir/gconv-modules]) @@ -582,6 +591,9 @@ AM_COND_IF([WITH_QVIDCAP], [USE_QVIDCAP="yes"], [USE_QVIDCAP="no"]) AM_COND_IF([WITH_V4L_PLUGINS], [USE_V4L_PLUGINS="yes" AC_DEFINE([HAVE_V4L_PLUGINS], [1], [V4L plugin support enabled])], [USE_V4L_PLUGINS="no"]) +AM_COND_IF([WITH_V4L_BUILTIN_PLUGINS], [USE_V4L_BUILTIN_PLUGINS="yes" + AC_DEFINE([HAVE_V4L_BUILTIN_PLUGINS], [1], [V4L builtin plugin support enabled])], + [USE_V4L_BUILTIN_PLUGINS="no"]) AM_COND_IF([WITH_V4L_WRAPPERS], [USE_V4L_WRAPPERS="yes"], [USE_V4L_WRAPPERS="no"]) AM_COND_IF([WITH_GCONV], [USE_GCONV="yes"], [USE_GCONV="no"]) AM_COND_IF([WITH_V4L2_CTL_LIBV4L], [USE_V4L2_CTL_LIBV4L="yes"], [USE_V4L2_CTL_LIBV4L="no"]) @@ -628,6 +640,7 @@ compile time options summary dynamic libv4l : $USE_DYN_LIBV4L v4l_plugins : $USE_V4L_PLUGINS + v4l_builtin_plugins : $USE_V4L_BUILTIN_PLUGINS v4l_wrappers : $USE_V4L_WRAPPERS libdvbv5 : $USE_LIBDVBV5 dvbv5-daemon : $USE_DVBV5_REMOTE diff --git a/lib/Makefile.am b/lib/Makefile.am index a105c95a..4952d6d1 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -1,9 +1,9 @@ SUBDIRS = \ + libv4l-mplane \ libv4lconvert \ libv4l2 \ libv4l1 \ - libv4l2rds \ - libv4l-mplane + libv4l2rds if WITH_LIBDVBV5 SUBDIRS += \ diff --git a/lib/libv4l-mplane/Makefile.am b/lib/libv4l-mplane/Makefile.am index 5264ecf2..4c0ba0a3 100644 --- a/lib/libv4l-mplane/Makefile.am +++ b/lib/libv4l-mplane/Makefile.am @@ -1,7 +1,16 @@ +if WITH_V4L_BUILTIN_PLUGINS +noinst_LTLIBRARIES = libv4l-mplane.la +else if WITH_V4L_PLUGINS libv4l2plugin_LTLIBRARIES = libv4l-mplane.la endif +endif libv4l_mplane_la_SOURCES = libv4l-mplane.c +if WITH_V4L_BUILTIN_PLUGINS +libv4l_mplane_la_CPPFLAGS = -static +libv4l_mplane_la_LDFLAGS = -static +else libv4l_mplane_la_CPPFLAGS = $(CFLAG_VISIBILITY) libv4l_mplane_la_LDFLAGS = -avoid-version -module -shared -export-dynamic -lpthread +endif diff --git a/lib/libv4l-mplane/libv4l-mplane.c b/lib/libv4l-mplane/libv4l-mplane.c index db22b0b4..fcd522e3 100644 --- a/lib/libv4l-mplane/libv4l-mplane.c +++ b/lib/libv4l-mplane/libv4l-mplane.c @@ -609,7 +609,11 @@ static ssize_t plugin_write(void *dev_ops_priv, int fd, const void *buf, return SYS_WRITE(fd, buf, len); } +#ifdef HAVE_V4L_BUILTIN_PLUGINS +const struct libv4l_dev_ops libv4l2_plugin_mplane = { +#else PLUGIN_PUBLIC const struct libv4l_dev_ops libv4l2_plugin = { +#endif .init = &plugin_init, .close = &plugin_close, .ioctl = &plugin_ioctl, diff --git a/lib/libv4l2/Makefile.am b/lib/libv4l2/Makefile.am index 3a1bb901..1250d840 100644 --- a/lib/libv4l2/Makefile.am +++ b/lib/libv4l2/Makefile.am @@ -23,6 +23,9 @@ endif libv4l2_la_CPPFLAGS = $(CFLAG_VISIBILITY) $(ENFORCE_LIBV4L_STATIC) libv4l2_la_LDFLAGS = $(LIBV4L2_VERSION) -lpthread $(DLOPEN_LIBS) $(ENFORCE_LIBV4L_STATIC) libv4l2_la_LIBADD = ../libv4lconvert/libv4lconvert.la +if WITH_V4L_BUILTIN_PLUGINS +libv4l2_la_LIBADD += ../libv4l-mplane/libv4l-mplane.la +endif v4l2convert_la_SOURCES = v4l2convert.c v4l2convert_la_LIBADD = libv4l2.la diff --git a/lib/libv4l2/libv4l2-priv.h b/lib/libv4l2/libv4l2-priv.h index cce6de43..cc8c4f57 100644 --- a/lib/libv4l2/libv4l2-priv.h +++ b/lib/libv4l2/libv4l2-priv.h @@ -109,20 +109,20 @@ struct v4l2_dev_info { /* From v4l2-plugin.c */ #if defined(HAVE_V4L_PLUGINS) -void v4l2_plugin_init(int fd, void **plugin_lib_ret, void **plugin_priv_ret, - const struct libv4l_dev_ops **dev_ops_ret); -void v4l2_plugin_cleanup(void *plugin_lib, void *plugin_priv, - const struct libv4l_dev_ops *dev_ops); +void v4l2_dyn_plugin_init(int fd, void **plugin_lib_ret, void **plugin_priv_ret, + const struct libv4l_dev_ops **dev_ops_ret); +void v4l2_dyn_plugin_cleanup(void *plugin_lib, void *plugin_priv, + const struct libv4l_dev_ops *dev_ops); #else -static inline void v4l2_plugin_init(int fd, void **plugin_lib_ret, void **plugin_priv_ret, - const struct libv4l_dev_ops **dev_ops_ret) +static inline void v4l2_dyn_plugin_init(int fd, void **plugin_lib_ret, void **plugin_priv_ret, + const struct libv4l_dev_ops **dev_ops_ret) { *dev_ops_ret = v4lconvert_get_default_dev_ops(); *plugin_lib_ret = NULL; *plugin_priv_ret = NULL; } -static inline void v4l2_plugin_cleanup(void *plugin_lib, void *plugin_priv, - const struct libv4l_dev_ops *dev_ops) +static inline void v4l2_dyn_plugin_cleanup(void *plugin_lib, void *plugin_priv, + const struct libv4l_dev_ops *dev_ops) { } #endif /* WITH_V4L_PLUGINS */ diff --git a/lib/libv4l2/libv4l2.c b/lib/libv4l2/libv4l2.c index 0b178889..949a0209 100644 --- a/lib/libv4l2/libv4l2.c +++ b/lib/libv4l2/libv4l2.c @@ -74,6 +74,8 @@ #include "libv4l2-priv.h" #include "libv4l-plugin.h" +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + /* Note these flags are stored together with the flags passed to v4l2_fd_open() in v4l2_dev_info's flags member, so care should be taken that the do not use the same bits! */ @@ -618,6 +620,77 @@ static void v4l2_update_fps(int index, struct v4l2_streamparm *parm) devices[index].fps = 0; } +#ifdef HAVE_V4L_BUILTIN_PLUGINS +extern const struct libv4l_dev_ops libv4l2_plugin_mplane; + +void v4l2_builtin_plugin_init(int fd, void **plugin_priv_ret, + const struct libv4l_dev_ops **dev_ops_ret) +{ + const struct libv4l_dev_ops *builtin_plugins[] = { + &libv4l2_plugin_mplane, + }; + const struct libv4l_dev_ops *libv4l2_plugin = NULL; + int i; + + *dev_ops_ret = NULL; + *plugin_priv_ret = NULL; + + for (i = 0; i < ARRAY_SIZE(builtin_plugins); i++) { + V4L2_LOG("PLUGIN: try builtin(%d);\n", i); + + libv4l2_plugin = builtin_plugins[i]; + + if (!libv4l2_plugin->init || + !libv4l2_plugin->close || + !libv4l2_plugin->ioctl) { + V4L2_LOG("PLUGIN: does not have all mandatory ops\n"); + continue; + } + + *plugin_priv_ret = libv4l2_plugin->init(fd); + if (!*plugin_priv_ret) { + V4L2_LOG("PLUGIN: plugin init() returned NULL\n"); + continue; + } + + *dev_ops_ret = libv4l2_plugin; + break; + } +} + +void v4l2_builtin_plugin_cleanup(void *plugin_priv, + const struct libv4l_dev_ops *dev_ops) +{ + dev_ops->close(plugin_priv); +} +#endif /* HAVE_V4L_PLUGINS */ + +void v4l2_plugin_init(int fd, void **plugin_lib_ret, void **plugin_priv_ret, + const struct libv4l_dev_ops **dev_ops_ret) +{ +#ifdef HAVE_V4L_BUILTIN_PLUGINS + *plugin_lib_ret = NULL; + v4l2_builtin_plugin_init(fd, plugin_priv_ret, dev_ops_ret); + if (*dev_ops_ret) + return; +#endif + + v4l2_dyn_plugin_init(fd, plugin_lib_ret, plugin_priv_ret, dev_ops_ret); +} + +void v4l2_plugin_cleanup(void *plugin_lib, void *plugin_priv, + const struct libv4l_dev_ops *dev_ops) +{ +#ifdef HAVE_V4L_BUILTIN_PLUGINS + if (!plugin_lib) { + v4l2_builtin_plugin_cleanup(plugin_priv, dev_ops); + return; + } +#endif + + v4l2_dyn_plugin_cleanup(plugin_lib, plugin_priv, dev_ops); +} + int v4l2_open(const char *file, int oflag, ...) { int fd; diff --git a/lib/libv4l2/v4l2-plugin.c b/lib/libv4l2/v4l2-plugin.c index ff42eed4..f65baaa4 100644 --- a/lib/libv4l2/v4l2-plugin.c +++ b/lib/libv4l2/v4l2-plugin.c @@ -48,8 +48,8 @@ #define PLUGINS_PATTERN LIBV4L2_PLUGIN_DIR "/*.so" -void v4l2_plugin_init(int fd, void **plugin_lib_ret, void **plugin_priv_ret, - const struct libv4l_dev_ops **dev_ops_ret) +void v4l2_dyn_plugin_init(int fd, void **plugin_lib_ret, void **plugin_priv_ret, + const struct libv4l_dev_ops **dev_ops_ret) { char *error; int glob_ret, i; @@ -110,8 +110,8 @@ leave: globfree(&globbuf); } -void v4l2_plugin_cleanup(void *plugin_lib, void *plugin_priv, - const struct libv4l_dev_ops *dev_ops) +void v4l2_dyn_plugin_cleanup(void *plugin_lib, void *plugin_priv, + const struct libv4l_dev_ops *dev_ops) { if (plugin_lib) { dev_ops->close(plugin_priv); -- 2.20.1