[libav-devel] [PATCH 2/3] omx: Add support for broadcom OMX on raspberry pi

Martin Storsjö martin at martin.st
Thu Apr 7 11:47:37 CEST 2016


The raspberry pi uses the alternative API/ABI for OMX; this makes
such builds incompatible with all the normal OpenMAX implementations.
Since this can't easily be detected at configure time (one can
build for raspberry pi's OMX just fine using the generic, pristine
Khronos OpenMAX IL headers, no need for their own extensions),
require a separate configure switch for it instead.

The broadcom host library can't be unloaded once loaded and started;
the deinit function that it provides is a no-op, and after started,
it has got background threads running, so dlclosing it makes it
crash.
---
 configure        | 12 +++++++++++-
 libavcodec/omx.c | 51 +++++++++++++++++++++++++++++++++++++++++++++------
 2 files changed, 56 insertions(+), 7 deletions(-)

diff --git a/configure b/configure
index 4a3e570..c6cf050 100755
--- a/configure
+++ b/configure
@@ -226,6 +226,7 @@ External library support:
   --enable-mmal            enable decoding via MMAL [no]
   --enable-nvenc           enable encoding via NVENC [no]
   --enable-omx             enable encoding via OpenMAX IL [no]
+  --enable-rpi-omx         enable encoding via OpenMAX IL for Raspberry Pi [no]
   --enable-openssl         enable openssl [no]
   --enable-x11grab         enable X11 grabbing (legacy) [no]
   --enable-zlib            enable zlib [autodetect]
@@ -1262,6 +1263,7 @@ EXTERNAL_LIBRARY_LIST="
 FEATURE_LIST="
     gray
     hardcoded_tables
+    rpi_omx
     runtime_cpudetect
     safe_bitstream_reader
     shared
@@ -4608,7 +4610,15 @@ enabled mmal              && { check_lib interface/mmal/mmal.h mmal_port_connect
                                     check_lib interface/mmal/mmal.h mmal_port_connect ; }
                                 check_lib interface/mmal/mmal.h mmal_port_connect ; } ||
                                die "ERROR: mmal not found"; }
-enabled omx               && { check_header OMX_Core.h || die "ERROR: OpenMAX IL headers not found"; }
+if enabled rpi_omx; then
+    enable omx
+    add_cflags -DOMX_SKIP64BIT
+fi
+enabled omx               && { check_header OMX_Core.h ||
+                                { ! enabled cross_compile && enabled rpi_omx && {
+                                    add_cflags -isystem/opt/vc/include/IL ; }
+                                check_header OMX_Core.h ; } ||
+                               die "ERROR: OpenMAX IL headers not found"; }
 enabled openssl           && { check_pkg_config openssl openssl/ssl.h SSL_library_init && {
                                add_cflags $openssl_cflags && add_extralibs $openssl_libs; }||
                                check_lib openssl/ssl.h SSL_library_init -lssl -lcrypto ||
diff --git a/libavcodec/omx.c b/libavcodec/omx.c
index 323a580..b50376c 100644
--- a/libavcodec/omx.c
+++ b/libavcodec/omx.c
@@ -19,6 +19,8 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include "config.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 
@@ -54,6 +56,7 @@ static int64_t fromOmxTicks(OMX_TICKS value) {
 typedef struct OMXContext {
     int users;
     void *lib;
+    void *lib2;
     OMX_ERRORTYPE (*ptr_Init)(void);
     OMX_ERRORTYPE (*ptr_Deinit)(void);
     OMX_ERRORTYPE (*ptr_ComponentNameEnum)(OMX_STRING, OMX_U32, OMX_U32);
@@ -61,6 +64,7 @@ typedef struct OMXContext {
     OMX_ERRORTYPE (*ptr_FreeHandle)(OMX_HANDLETYPE);
     OMX_ERRORTYPE (*ptr_GetComponentsOfRole)(OMX_STRING, OMX_U32*, OMX_U8**);
     OMX_ERRORTYPE (*ptr_GetRolesOfComponent)(OMX_STRING, OMX_U32*, OMX_U8**);
+    void (*host_init)(void);
 } OMXContext;
 
 static OMXContext *omx_context;
@@ -73,9 +77,23 @@ static av_cold void *dlsym2(void *handle, const char *symbol, const char *prefix
     return dlsym(handle, buf);
 }
 
-static av_cold int omx_try_load(void *logctx, const char *libname, const char *prefix)
+static av_cold int omx_try_load(void *logctx, const char *libname, const char *prefix, const char *libname2)
 {
     OMXContext *s = omx_context;
+    if (libname2) {
+        s->lib2 = dlopen(libname2, RTLD_NOW | RTLD_GLOBAL);
+        if (!s->lib2) {
+            av_log(logctx, AV_LOG_WARNING, "%s not found\n", libname);
+            return AVERROR_ENCODER_NOT_FOUND;
+        }
+        s->host_init = dlsym(s->lib2, "bcm_host_init");
+        if (!s->host_init) {
+            av_log(logctx, AV_LOG_WARNING, "bcm_host_init not found\n");
+            dlclose(s->lib2);
+            s->lib2 = NULL;
+            return AVERROR_ENCODER_NOT_FOUND;
+        }
+    }
     s->lib = dlopen(libname, RTLD_NOW | RTLD_GLOBAL);
     if (!s->lib) {
         av_log(logctx, AV_LOG_WARNING, "%s not found\n", libname);
@@ -94,6 +112,9 @@ static av_cold int omx_try_load(void *logctx, const char *libname, const char *p
         av_log(logctx, AV_LOG_WARNING, "Not all functions found in %s\n", libname);
         dlclose(s->lib);
         s->lib = NULL;
+        if (s->lib2)
+            dlclose(s->lib2);
+        s->lib2 = NULL;
         return AVERROR_ENCODER_NOT_FOUND;
     }
     return 0;
@@ -101,8 +122,12 @@ static av_cold int omx_try_load(void *logctx, const char *libname, const char *p
 
 static av_cold int omx_init(void *logctx, const char *libname, const char *prefix) {
     static const char * const libnames[] = {
-        "libOMX_Core.so",
-        "libOmxCore.so",
+#if CONFIG_RPI_OMX
+        "/opt/vc/lib/libopenmaxil.so", "/opt/vc/lib/libbcm_host.so",
+#else
+        "libOMX_Core.so", NULL,
+        "libOmxCore.so", NULL,
+#endif
         NULL
     };
     const char* const* nameptr;
@@ -122,14 +147,14 @@ static av_cold int omx_init(void *logctx, const char *libname, const char *prefi
     }
     omx_context->users = 1;
     if (libname) {
-        ret = omx_try_load(logctx, libname, prefix);
+        ret = omx_try_load(logctx, libname, prefix, NULL);
         if (ret < 0) {
             pthread_mutex_unlock(&omx_context_mutex);
             return ret;
         }
     } else {
-        for (nameptr = libnames; *nameptr; nameptr++)
-            if (!(ret = omx_try_load(logctx, *nameptr, prefix)))
+        for (nameptr = libnames; *nameptr; nameptr += 2)
+            if (!(ret = omx_try_load(logctx, nameptr[0], prefix, nameptr[1])))
                 break;
         if (!*nameptr) {
             pthread_mutex_unlock(&omx_context_mutex);
@@ -137,6 +162,8 @@ static av_cold int omx_init(void *logctx, const char *libname, const char *prefi
         }
     }
 
+    if (omx_context->host_init)
+        omx_context->host_init();
     omx_context->ptr_Init();
     pthread_mutex_unlock(&omx_context_mutex);
     return 0;
@@ -263,6 +290,12 @@ static av_cold int find_component(void *logctx, const char *role, char *str,
     char **components;
     int ret = 0;
 
+#if CONFIG_RPI_OMX
+    if (av_strstart(role, "video_encoder.", NULL)) {
+        av_strlcpy(str, "OMX.broadcom.video_encode", str_size);
+        return 0;
+    }
+#endif
     omx_context->ptr_GetComponentsOfRole((OMX_STRING) role, &num, NULL);
     if (!num) {
         av_log(logctx, AV_LOG_WARNING, "No component for role %s found\n", role);
@@ -325,6 +358,8 @@ static av_cold int omx_component_init(AVCodecContext *avctx, const char *role)
 
     s->version.s.nVersionMajor = 1;
     s->version.s.nVersionMinor = 1;
+    if (av_strstart(s->component_name, "OMX.broadcom.", NULL))
+        s->version.s.nRevision = 2;
 #define INIT_STRUCT(x) do { x.nSize = sizeof(x); x.nVersion = s->version; } while (0)
 
     err = omx_context->ptr_GetHandle(&s->handle, s->component_name, s, (OMX_CALLBACKTYPE*) &callbacks);
@@ -394,6 +429,10 @@ static av_cold int omx_component_init(AVCodecContext *avctx, const char *role)
     in_port_params.format.video.eColorFormat = s->color_format;
     s->stride = avctx->width;
     s->plane_size = avctx->height;
+    if (!strcmp(s->component_name, "OMX.broadcom.video_encode")) {
+        s->stride = FFALIGN(s->stride, 16);
+        s->plane_size = FFALIGN(s->plane_size, 16);
+    }
     in_port_params.format.video.nStride = s->stride;
     in_port_params.format.video.nSliceHeight = s->plane_size;
     if (avctx->framerate.den > 0 && avctx->framerate.num > 0)
-- 
2.1.4



More information about the libav-devel mailing list