Browse Source

POC_LIBVLC_PROTOCOL: add first version

Alexandre Janniaux 4 years ago
parent
commit
5b8d04fede
1 changed files with 154 additions and 0 deletions
  1. 154 0
      POC_LIBVLC_PROTOCOL.md

+ 154 - 0
POC_LIBVLC_PROTOCOL.md

@@ -0,0 +1,154 @@
+# Idea synopsys
+
+Expose LibVLC API and plugins through a dynamically generated API, much
+alike how Wayland protocol is exposed with libwayland-client.
+
+# Motivation
+
+The libvlccore library is very flexible and has a lot of dynamic
+entrypoints that can be filled with features from different plugins.
+
+However, the libvlc API currently cannot be "modularised" into
+different plugins. Thus, every features brought by the plugin need
+their API to be exposed in static form as symbols.
+
+It means that:
+
+ - When libVLC exposes an API to use with the plugin, this plugin
+   becomes mandatory in libVLC builds, so it removes one of the main
+   interest of plugins from the user point of view.
+
+ - An API exposed by libVLC is meant to be stable, so as soon as the
+   API exists, VLC Core and libVLC layers are tied to it.
+
+ - It exposes a lot of symbols in libVLC, which are usually redundant
+   with what libvlccore can expose.
+
+Instead, the motivation here is to see libVLC through the concept of:
+
+    « Plugin as an API »
+
+The libvlc interface can be stretched to the minimal to setup libvlc
+and expose global interfaces. Then most of the code can just be inline
+structure and inline code to setup and use those structures from the
+plugins.
+
+In particular, it also allow different level of support without ever
+breaking the API/ABI at the link level.
+
+Many features at Videolabs for clients, or prototypes of API that need
+to be tested and iterated before going to the stable API support level
+are currently made available directly through libVLC symbols, which
+means forks, unfinished function that need to be stabilized and
+sometimes big crude hacks to make things work.
+
+By exposing this API at the plugin level, it's possible to expose
+the work-in-progress features and customers features without making
+transgressions on the public «supported» libVLC API, and most of the
+time expose those features as plugins in official release instead of
+libVLC builds.
+
+# Example client code
+
+```
+libvlc_instance *instance = libvlc_instance_New(argc, argv);
+
+libvlc_plugin_interactive_zoom *zoom = NULL;
+
+static void object_added(
+    libvlc_discoverer *discoverer,
+    libvlc_object *object
+) {
+    /* The libvlc_discoverer_attach_object must do some dark magic for
+     * the binding of protocol. In particular, it must return an object
+     * of type `libvlc_plugin_interactive_zoom *` (automatically casted
+     * from `void *` in C) that must be created by the probe proxy.
+    if (object->name == "vlc_filter_interactive_zoom")
+        zoom = libvlc_plugin_interactive_zoom_attach_object(
+            discoverer, object, INTERACTIVE_ZOOM_VERSION, NULL /*opaque*/
+        );
+
+        /* The code above is the type safe variant of
+            zoom = libvlc_discoverer_attach_object(
+                discoverer, object,
+                libvlc_plugin_interactive_zoom_interface,
+                INTERACTIVE_ZOOM_VERSION
+        */
+}
+
+libvlc_discovery_callbacks callbacks = {
+    .added = object_added,
+    .removed = object_removed,
+};
+
+libvlc_discoverer *discoverer = libvlc_discoverer_new(instance);
+
+/* Enable some global features */
+libvlc_discoverer_add_option(/* ... */);
+libvlc_discoverer_add_option(/* ... */);
+libvlc_discoverer_add_option(/* ... */);
+
+/* Setup global objects */
+libvlc_discover(instance, &callbacks);
+
+/* global objects are attached to the libvlc discoverer */
+
+/* Interface callback for zoom */
+static int onZoomPerformed(zoom_params params) {
+    /* Check that we can use the interactive zoom API */
+    if (zoom == NULL)
+        return ENOTSUPPORTED;
+
+    libvlc_plugin_interactive_zoom_zoom(zoom, params.x, params.y);
+}
+```
+
+# Exemple server code
+
+```
+/* create a proxy interface object which must expose the interface */
+static void *create_proxy(
+    vlc_api_t *api,
+    const char *name,
+    unsigned version,
+    const void *listener;
+) {
+    VLC_UNUSED(name);
+
+    /* Generated:
+     *  - libvlc_listener_plugin_interactive_zoom (events handling)
+     *  - libvlc_plugin_interactive_zoom (requests pointer table)
+     **/
+    struct libvlc_wrapper_plugin_interactive_zoom {
+        libvlc_listener_plugin_interactive_zoom *listener;
+        libvlc_plugin_interactive_zoom interface;
+    };
+    libvlc_wrapper_plugin_interactive_zoom *zoom = malloc(sizeof *zoom);
+    if (!zoom) return NULL;
+
+    zoom->listener = listener;
+    zoom->interface = (struct libvlc_plugin_interactive_zoom) {
+        .zoom = DoZoom
+    };
+
+    return &zoom->interface;
+}
+
+/* probe proxy exposing the API entrypoint and the creation
+ * function */
+static int OpenAPI(vlc_api_t *api)
+{
+    vlc_api_DefineGlobalObject(api,
+        "vlc_filter_interactive_zoom",
+        API_VERSION, &create_proxy)
+}
+
+vlc_module_begin()
+    add_capability("api interface", API_VERSION)
+    set_callback(OpenAPI)
+
+    add_submodule()
+        add_capability("video filter", 0)
+        set_callbacks(Open, Close)
+vlc_module_end()
+```