[x265] [PATCH RFC] api: introduce a less version strict API query

Steve Borho steve at borho.org
Thu May 14 19:53:01 CEST 2015


# HG changeset patch
# User Steve Borho <steve at borho.org>
# Date 1431625954 18000
#      Thu May 14 12:52:34 2015 -0500
# Node ID 6c0bd18d02eaf8b141368c5ecee417ba61f7ed85
# Parent  8592bf81d0848279fa79cd1487406cb516dffe99
api: introduce a less version strict API query

The intention is to allow applications to use libx265 libraries with different
X265_BUILD numbers than the x265.h header they were compiled with by keeping
a little more information about the nature of each API bump.

This should have no effect on existing applications, X265_BUILD will still be
incremented each time the public API is changed, but applications which use
this new x265_get_api_build() method will be able to dlopen() and use any
version of libx265 that returns an API pointer that passes validation checks:

  1. check api->api_major_version == X265_MAJOR_VERSION
  2. check api->sizeof_param == sizeof(x265_param) if param is dereferenced
  3. check api->sizeof_picture == sizeof(x265_picture)
  4. check api->sizeof_analysis_data ..
    etc.

apps that use param_alloc()/param_free()/param_parse() can skip step 2 and
thus ignore the primary cause of most X265_BUILD bumps.

The only additional work for x265 developers is to increment X265_MAJOR_VERSION
when warranted (which should hopefully be very rarely).

Since this commit is modifying x265_api, we take the opportunity to rename
max_bit_depth to the more accurate bit_depth, since each API will only be
capable of encoding at a single bit depth. Obviously this commit would also
need to bump X265_BUILD before being pushed.

diff -r 8592bf81d084 -r 6c0bd18d02ea source/encoder/api.cpp
--- a/source/encoder/api.cpp	Thu May 14 17:12:14 2015 +0530
+++ b/source/encoder/api.cpp	Thu May 14 12:52:34 2015 -0500
@@ -253,6 +253,18 @@
 
 static const x265_api libapi =
 {
+    X265_MAJOR_VERSION,
+    X265_BUILD,
+    sizeof(x265_param),
+    sizeof(x265_picture),
+    sizeof(x265_analysis_data),
+    sizeof(x265_zone),
+    sizeof(x265_stats),
+
+    x265_max_bit_depth,
+    x265_version_str,
+    x265_build_info_str,
+
     &x265_param_alloc,
     &x265_param_free,
     &x265_param_default,
@@ -271,9 +283,6 @@
     &x265_encoder_log,
     &x265_encoder_close,
     &x265_cleanup,
-    x265_version_str,
-    x265_build_info_str,
-    x265_max_bit_depth,
 };
 
 typedef const x265_api* (*api_get_func)(int bitDepth);
@@ -337,7 +346,7 @@
             x265_log(NULL, X265_LOG_WARNING, "Unable to open %s\n", libname);
 #endif
 
-        if (api && bitDepth != api->max_bit_depth)
+        if (api && bitDepth != api->bit_depth)
         {
             x265_log(NULL, X265_LOG_WARNING, "%s does not support requested bitDepth %d\n", libname, bitDepth);
             return NULL;
diff -r 8592bf81d084 -r 6c0bd18d02ea source/x265.cpp
--- a/source/x265.cpp	Thu May 14 17:12:14 2015 +0530
+++ b/source/x265.cpp	Thu May 14 12:52:34 2015 -0500
@@ -318,9 +318,9 @@
         return true;
     }
 
-    if (param->internalBitDepth != api->max_bit_depth)
+    if (param->internalBitDepth != api->bit_depth)
     {
-        x265_log(param, X265_LOG_ERROR, "Only bit depths of %d are supported in this build\n", api->max_bit_depth);
+        x265_log(param, X265_LOG_ERROR, "Only bit depths of %d are supported in this build\n", api->bit_depth);
         return true;
     }
 
diff -r 8592bf81d084 -r 6c0bd18d02ea source/x265.def.in
--- a/source/x265.def.in	Thu May 14 17:12:14 2015 +0530
+++ b/source/x265.def.in	Thu May 14 12:52:34 2015 -0500
@@ -21,3 +21,4 @@
 x265_encoder_close
 x265_cleanup
 x265_api_get_${X265_BUILD}
+x265_api_get_build
diff -r 8592bf81d084 -r 6c0bd18d02ea source/x265.h
--- a/source/x265.h	Thu May 14 17:12:14 2015 +0530
+++ b/source/x265.h	Thu May 14 12:52:34 2015 -0500
@@ -1278,15 +1278,28 @@
  *       release library static allocations, reset configured CTU size */
 void x265_cleanup(void);
 
+#define X265_MAJOR_VERSION 1
 
 /* === Multi-lib API ===
- * By using this method to gain access to the libx265 interfaces, you allow shim
- * implementations of x265_api_get() to choose between various available libx265
- * libraries based on the encoder parameters. The most likely use case is to
- * choose between 8bpp and 16bpp builds of libx265. */
+ * By using this method to gain access to the libx265 interfaces, you allow run-
+ * time selection between various available libx265 libraries based on the
+ * encoder parameters. The most likely use case is to choose between 8bpp and
+ * 16bpp builds of libx265. */
 
 typedef struct x265_api
 {
+    int           api_major_version;    /* X265_MAJOR_VERSION */
+    int           api_minor_version;    /* X265_BUILD (soname) */
+    int           sizeof_param;         /* sizeof(x265_param) */
+    int           sizeof_picture;       /* sizeof(x265_picture) */
+    int           sizeof_analysis_data; /* sizeof(x265_analysis_data) */
+    int           sizeof_zone;          /* sizeof(x265_zone) */
+    int           sizeof_stats;         /* sizeof(x265_stats) */
+
+    int           bit_depth;
+    const char*   version_str;
+    const char*   build_info_str;
+
     /* libx265 public API functions, documented above with x265_ prefixes */
     x265_param*   (*param_alloc)(void);
     void          (*param_free)(x265_param*);
@@ -1306,9 +1319,7 @@
     void          (*encoder_log)(x265_encoder*, int, char**);
     void          (*encoder_close)(x265_encoder*);
     void          (*cleanup)(void);
-    const char*   version_str;
-    const char*   build_info_str;
-    int           max_bit_depth;
+    /* add new pointers to the end, or increment X265_MAJOR_VERSION */
 } x265_api;
 
 /* Force a link error in the case of linking against an incompatible API version.
@@ -1332,6 +1343,29 @@
  *   Obviously the shared library file extension is platform specific */
 const x265_api* x265_api_get(int bitDepth);
 
+/* x265_api_get_build:
+ *   Retrieve the programming interface for a linked x265 library, like
+ *   x265_api_get(), except this function accepts X265_BUILD as the second
+ *   argument rather than using the build number as part of the function name.
+ *   Applications which dynamically link to libx265 can use this interface to
+ *   query the library API and achieve a relative amount of version skew
+ *   flexibility. The function may return NULL if the library determines that
+ *   the apiVersion that your application was compiled against is not compatible
+ *   with the library you have linked with.
+ *
+ *   api_major_version will be incremented any time struct x265_api is changed,
+ *   or if any non-backward compatible changes are made to any other public
+ *   structures or functions. If api_major_version does not match
+ *   X265_MAJOR_VERSION from the x265.h your application compiled against, your
+ *   application must not use the returned x265_api pointer.
+ *
+ *   Users of this API *must* also validate the sizes of any structures which
+ *   are not treated as opaque in application code. For instance, if your
+ *   application dereferences a x265_param pointer, then it must check that
+ *   api->sizeof_param matches the sizeof(x265_param) that your application
+ *   compiled with. */
+const x265_api* x265_api_get_build(int bitDepth, int apiVersion);
+
 #ifdef __cplusplus
 }
 #endif


More information about the x265-devel mailing list