Hi,

Attached is a preliminary patch that enables runtime loading of external
libraries via dlopen and friends. Dynamic loading is a build time option
(--enable-dynamic-loading) and if it is not activated the libs are
linked as usual (still no dependency to dlopen required).

The patch is intended as a basis for a discussion and therefore the
following applies:

- only libmp3lame and libva will by dynamically loaded atm
- only tested on linux atm
- deregistering not implemented (dlclose)
- versioning (which version of a lib should be loaded?)
- library usage counter missing
- ...?

What do you think?

Thanks,

Marc
diff --git a/configure b/configure
index 94f9432..5787101 100755
--- a/configure
+++ b/configure
@@ -101,6 +101,8 @@ Licensing options:
 Configuration options:
   --disable-static         do not build static libraries [no]
   --enable-shared          build shared libraries [no]
+  --enable-dynamic-loading enable runtime detection of installed libraries
+                           (disables compile time linking of third party libs)
   --enable-small           optimize for size instead of speed
   --disable-runtime-cpudetect disable detecting cpu capabilities at runtime (smaller binary)
   --enable-gray            enable full grayscale support (slower color)
@@ -1079,6 +1081,15 @@ check_lib(){
     check_header $header && check_func $func "$@" && add_extralibs "$@"
 }
 
+check_ext_lib() {
+    log check_ext_lib "$@"
+    header="$1"
+    func="$2"
+    shift 2
+    check_header $header && check_func $func "$@"
+    enabled dynamic_loading || add_extralibs "$@"
+}
+
 check_lib2(){
     log check_lib2 "$@"
     headers="$1"
@@ -1192,6 +1203,14 @@ require(){
     check_lib $header $func "$@" || die "ERROR: $name not found"
 }
 
+require_extlib(){
+    name="$1"
+    header="$2"
+    func="$3"
+    shift 3
+    check_ext_lib $header $func "$@" || die "ERROR: $name not found"
+}
+
 require2(){
     name="$1"
     headers="$2"
@@ -1432,6 +1451,7 @@ FEATURE_LIST="
     small
     static
     swscale_alpha
+    dynamic_loading
 "
 
 HWACCEL_LIST="
@@ -4855,6 +4875,10 @@ for func in $MATH_FUNCS; do
     eval check_mathfunc $func \${${func}_args:-1}
 done
 
+enabled dynamic_loading   && { { check_lib2 "windows.h" LoadLibrary; } ||
+                               { check_lib2 "dlfcn.h" dlopen -ldl; } ||
+                               die "ERROR: LoadLibrary/dlopen not found for dynamic-loading"; }
+
 # these are off by default, so fail if requested and not available
 enabled avfoundation_indev && { check_header_oc AVFoundation/AVFoundation.h || disable avfoundation_indev; }
 enabled avisynth          && { { check_lib2 "windows.h" LoadLibrary; } ||
@@ -4887,7 +4911,7 @@ enabled libgsm            && { for gsm_hdr in "gsm.h" "gsm/gsm.h"; do
                                done || die "ERROR: libgsm not found"; }
 enabled libilbc           && require libilbc ilbc.h WebRtcIlbcfix_InitDecode -lilbc
 enabled libmodplug        && require_pkg_config libmodplug libmodplug/modplug.h ModPlug_Load
-enabled libmp3lame        && require "libmp3lame >= 3.98.3" lame/lame.h lame_set_VBR_quality -lmp3lame
+enabled libmp3lame        && require_extlib "libmp3lame >= 3.98.3" lame/lame.h lame_set_VBR_quality -lmp3lame
 enabled libnut            && require libnut libnut.h nut_demuxer_init -lnut
 enabled libopencore_amrnb && require libopencore_amrnb opencore-amrnb/interf_dec.h Decoder_Interface_init -lopencore-amrnb
 enabled libopencore_amrwb && require libopencore_amrwb opencore-amrwb/dec_if.h D_IF_init -lopencore-amrwb
@@ -5109,7 +5133,7 @@ int main(void) { IDirectXVideoDecoder *o = NULL; IDirectXVideoDecoder_Release(o)
 EOF
 
 enabled vaapi &&
-    check_lib va/va.h vaInitialize -lva ||
+    check_ext_lib va/va.h vaInitialize -lva ||
     disable vaapi
 
 enabled vdpau &&
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 99467bb..4928b20 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -3228,7 +3228,7 @@ typedef struct AVCodec {
     /**
      * Initialize codec static data, called from avcodec_register().
      */
-    void (*init_static_data)(struct AVCodec *codec);
+    int (*init_static_data)(struct AVCodec *codec);
 
     int (*init)(AVCodecContext *);
     int (*encode_sub)(AVCodecContext *, uint8_t *buf, int buf_size,
@@ -3373,6 +3373,11 @@ typedef struct AVHWAccel {
     void (*decode_mb)(struct MpegEncContext *s);
 
     /**
+    * Initialize codec static data, called from av_register_hwaccel().
+    */
+    int (*init_static_data)(struct AVHWAccel *hwaccel);
+
+    /**
      * Initialize the hwaccel private data.
      *
      * This will be called from ff_get_format(), after hwaccel and
diff --git a/libavcodec/internal.h b/libavcodec/internal.h
index f4e12e8..fbfb8b8 100644
--- a/libavcodec/internal.h
+++ b/libavcodec/internal.h
@@ -45,6 +45,20 @@
 #   define STRIDE_ALIGN 8
 #endif
 
+
+#if CONFIG_DYNAMIC_LOADING
+#define FUNC_DEF(struct_name, func_name) {#func_name, (void **)&struct_name.func_name, NULL}
+#else
+#define FUNC_DEF(struct_name, func_name) {#func_name, (void **)&struct_name.func_name, func_name}
+#endif
+
+typedef struct FuncDef {
+    const char *func_name;
+    void **dest_func_ptr;
+    void *source_func_ptr;
+} FuncDef;
+
+
 typedef struct FramePool {
     /**
      * Pools for each data plane. For audio all the planes have the same size,
@@ -266,4 +280,6 @@ int ff_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt);
  */
 int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame);
 
+int resolve_symbols(const char *library_name, void **dlhandle, FuncDef *func_defs);
+
 #endif /* AVCODEC_INTERNAL_H */
diff --git a/libavcodec/libmp3lame.c b/libavcodec/libmp3lame.c
index e33919b..4dca65f 100644
--- a/libavcodec/libmp3lame.c
+++ b/libavcodec/libmp3lame.c
@@ -40,6 +40,46 @@
 
 #define BUFFER_SIZE (7200 + 2 * MPA_FRAME_SIZE + MPA_FRAME_SIZE / 4+1000) // FIXME: Buffer size to small? Adding 1000 to make up for it.
 
+#define TOSTRING(x) #x
+#define STR(x) TOSTRING(x)
+#ifdef _WIN32
+#define LIBRARY_PREFIX
+#else
+#define LIBRARY_PREFIX lib
+#endif
+
+#define LIBRARY_SHORT_NAME mp3lame
+#define LIBRARY_NAME STR(LIBRARY_PREFIX) STR(LIBRARY_SHORT_NAME) SLIBSUF
+
+
+static struct LAMESymbols {
+    void *dlhandle;
+
+    int (*lame_close)(lame_global_flags *);
+    int (*lame_encode_buffer_float)( lame_global_flags* gfp, const float pcm_l [],
+            const float pcm_r [], const int nsamples, unsigned char* mp3buf, const int mp3buf_size);
+    int (*lame_encode_buffer) (lame_global_flags* gfp, const short int buffer_l [],
+            const short int buffer_r [], const int nsamples, unsigned char* mp3buf, const int mp3buf_size);
+    int (*lame_encode_buffer_int)( lame_global_flags*  gfp, const int buffer_l [],
+            const int buffer_r [], const int nsamples, unsigned char* mp3buf, const int mp3buf_size);
+    int (*lame_encode_flush)( lame_global_flags * gfp, unsigned char* mp3buf, int size);
+    lame_global_flags* (*lame_init)(void);
+    int (*lame_set_num_channels)(lame_global_flags *, int);
+    int (*lame_set_mode)(lame_global_flags *, MPEG_mode);
+    int (*lame_set_in_samplerate)(lame_global_flags *, int);
+    int (*lame_set_out_samplerate)(lame_global_flags *, int);
+    int (*lame_set_quality)(lame_global_flags *, int);
+    int (*lame_set_VBR)(lame_global_flags *, vbr_mode);
+    int (*lame_set_VBR_quality)(lame_global_flags *, float);
+    int (*lame_set_VBR_mean_bitrate_kbps)(lame_global_flags *, int);
+    int (*lame_set_brate)(lame_global_flags *, int);
+    int (*lame_set_bWriteVbrTag)(lame_global_flags *, int);
+    int (*lame_set_disable_reservoir)(lame_global_flags *, int);
+    int (*lame_init_params)(lame_global_flags *);
+    int (*lame_get_encoder_delay)(const lame_global_flags *);
+    int (*lame_get_framesize)(const lame_global_flags *);
+} LAMESymbols;
+
 typedef struct LAMEContext {
     AVClass *class;
     AVCodecContext *avctx;
@@ -83,7 +123,7 @@ static av_cold int mp3lame_encode_close(AVCodecContext *avctx)
 
     ff_af_queue_close(&s->afq);
 
-    lame_close(s->gfp);
+    LAMESymbols.lame_close(s->gfp);
     return 0;
 }
 
@@ -95,52 +135,52 @@ static av_cold int mp3lame_encode_init(AVCodecContext *avctx)
     s->avctx = avctx;
 
     /* initialize LAME and get defaults */
-    if (!(s->gfp = lame_init()))
+    if (!(s->gfp = LAMESymbols.lame_init()))
         return AVERROR(ENOMEM);
 
 
-    lame_set_num_channels(s->gfp, avctx->channels);
-    lame_set_mode(s->gfp, avctx->channels > 1 ? s->joint_stereo ? JOINT_STEREO : STEREO : MONO);
+    LAMESymbols.lame_set_num_channels(s->gfp, avctx->channels);
+    LAMESymbols.lame_set_mode(s->gfp, avctx->channels > 1 ? s->joint_stereo ? JOINT_STEREO : STEREO : MONO);
 
     /* sample rate */
-    lame_set_in_samplerate (s->gfp, avctx->sample_rate);
-    lame_set_out_samplerate(s->gfp, avctx->sample_rate);
+    LAMESymbols.lame_set_in_samplerate (s->gfp, avctx->sample_rate);
+    LAMESymbols.lame_set_out_samplerate(s->gfp, avctx->sample_rate);
 
     /* algorithmic quality */
     if (avctx->compression_level != FF_COMPRESSION_DEFAULT)
-        lame_set_quality(s->gfp, avctx->compression_level);
+        LAMESymbols.lame_set_quality(s->gfp, avctx->compression_level);
 
     /* rate control */
     if (avctx->flags & CODEC_FLAG_QSCALE) { // VBR
-        lame_set_VBR(s->gfp, vbr_default);
-        lame_set_VBR_quality(s->gfp, avctx->global_quality / (float)FF_QP2LAMBDA);
+        LAMESymbols.lame_set_VBR(s->gfp, vbr_default);
+        LAMESymbols.lame_set_VBR_quality(s->gfp, avctx->global_quality / (float)FF_QP2LAMBDA);
     } else {
         if (avctx->bit_rate) {
             if (s->abr) {                   // ABR
-                lame_set_VBR(s->gfp, vbr_abr);
-                lame_set_VBR_mean_bitrate_kbps(s->gfp, avctx->bit_rate / 1000);
+                LAMESymbols.lame_set_VBR(s->gfp, vbr_abr);
+                LAMESymbols.lame_set_VBR_mean_bitrate_kbps(s->gfp, avctx->bit_rate / 1000);
             } else                          // CBR
-                lame_set_brate(s->gfp, avctx->bit_rate / 1000);
+                LAMESymbols.lame_set_brate(s->gfp, avctx->bit_rate / 1000);
         }
     }
 
     /* do not get a Xing VBR header frame from LAME */
-    lame_set_bWriteVbrTag(s->gfp,0);
+    LAMESymbols.lame_set_bWriteVbrTag(s->gfp,0);
 
     /* bit reservoir usage */
-    lame_set_disable_reservoir(s->gfp, !s->reservoir);
+    LAMESymbols.lame_set_disable_reservoir(s->gfp, !s->reservoir);
 
     /* set specified parameters */
-    if (lame_init_params(s->gfp) < 0) {
+    if (LAMESymbols.lame_init_params(s->gfp) < 0) {
         ret = -1;
         goto error;
     }
 
     /* get encoder delay */
-    avctx->initial_padding = lame_get_encoder_delay(s->gfp) + 528 + 1;
+    avctx->initial_padding = LAMESymbols.lame_get_encoder_delay(s->gfp) + 528 + 1;
     ff_af_queue_init(avctx, &s->afq);
 
-    avctx->frame_size  = lame_get_framesize(s->gfp);
+    avctx->frame_size  = LAMESymbols.lame_get_framesize(s->gfp);
 
     /* allocate float sample buffers */
     if (avctx->sample_fmt == AV_SAMPLE_FMT_FLTP) {
@@ -192,10 +232,10 @@ static int mp3lame_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
     if (frame) {
         switch (avctx->sample_fmt) {
         case AV_SAMPLE_FMT_S16P:
-            ENCODE_BUFFER(lame_encode_buffer, int16_t, frame->data);
+            ENCODE_BUFFER(LAMESymbols.lame_encode_buffer, int16_t, frame->data);
             break;
         case AV_SAMPLE_FMT_S32P:
-            ENCODE_BUFFER(lame_encode_buffer_int, int32_t, frame->data);
+            ENCODE_BUFFER(LAMESymbols.lame_encode_buffer_int, int32_t, frame->data);
             break;
         case AV_SAMPLE_FMT_FLTP:
             if (frame->linesize[0] < 4 * FFALIGN(frame->nb_samples, 8)) {
@@ -208,7 +248,7 @@ static int mp3lame_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
                                            32768.0f,
                                            FFALIGN(frame->nb_samples, 8));
             }
-            ENCODE_BUFFER(lame_encode_buffer_float, float, s->samples_flt);
+            ENCODE_BUFFER(LAMESymbols.lame_encode_buffer_float, float, s->samples_flt);
             break;
         default:
             return AVERROR_BUG;
@@ -216,7 +256,7 @@ static int mp3lame_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
     } else if (!s->afq.frame_alloc) {
         lame_result = 0;
     } else {
-        lame_result = lame_encode_flush(s->gfp, s->buffer + s->buffer_index,
+        lame_result = LAMESymbols.lame_encode_flush(s->gfp, s->buffer + s->buffer_index,
                                         s->buffer_size - s->buffer_index);
     }
     if (lame_result < 0) {
@@ -274,6 +314,45 @@ static int mp3lame_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
     return 0;
 }
 
+static av_cold int init_static_data(AVCodec *codec) {
+    struct FuncDef funcDefs[] = {
+            FUNC_DEF(LAMESymbols, lame_init),
+            FUNC_DEF(LAMESymbols, lame_close),
+            FUNC_DEF(LAMESymbols, lame_encode_buffer_float),
+            FUNC_DEF(LAMESymbols, lame_encode_buffer),
+            FUNC_DEF(LAMESymbols, lame_encode_buffer_int),
+            FUNC_DEF(LAMESymbols, lame_encode_flush),
+            FUNC_DEF(LAMESymbols, lame_set_num_channels),
+            FUNC_DEF(LAMESymbols, lame_set_mode),
+            FUNC_DEF(LAMESymbols, lame_set_in_samplerate),
+            FUNC_DEF(LAMESymbols, lame_set_out_samplerate),
+            FUNC_DEF(LAMESymbols, lame_set_quality),
+            FUNC_DEF(LAMESymbols, lame_set_VBR),
+            FUNC_DEF(LAMESymbols, lame_set_VBR_quality),
+            FUNC_DEF(LAMESymbols, lame_set_VBR_mean_bitrate_kbps),
+            FUNC_DEF(LAMESymbols, lame_set_brate),
+            FUNC_DEF(LAMESymbols, lame_set_bWriteVbrTag),
+            FUNC_DEF(LAMESymbols, lame_set_disable_reservoir),
+            FUNC_DEF(LAMESymbols, lame_init_params),
+            FUNC_DEF(LAMESymbols, lame_get_encoder_delay),
+            FUNC_DEF(LAMESymbols, lame_get_framesize),
+            { NULL },
+    };
+
+    /* libopus.0.dylib
+       libz.1.1.3.dylib
+
+       opus-0.dll
+       x264-142.dll
+       vpx-1.dll
+       vpx-1.3.dll
+       vpx-1.3.0.dll
+    */
+    return resolve_symbols(LIBRARY_NAME, &LAMESymbols.dlhandle, funcDefs);
+ }
+
+
+
 #define OFFSET(x) offsetof(LAMEContext, x)
 #define AE AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
 static const AVOption options[] = {
@@ -305,6 +384,7 @@ AVCodec ff_libmp3lame_encoder = {
     .type                  = AVMEDIA_TYPE_AUDIO,
     .id                    = AV_CODEC_ID_MP3,
     .priv_data_size        = sizeof(LAMEContext),
+    .init_static_data      = init_static_data,
     .init                  = mp3lame_encode_init,
     .encode2               = mp3lame_encode_frame,
     .close                 = mp3lame_encode_close,
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index 1ec5cae..2520e69 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -69,6 +69,25 @@
 #include "libavutil/ffversion.h"
 const char av_codec_ffversion[] = "FFmpeg version " FFMPEG_VERSION;
 
+#if CONFIG_DYNAMIC_LOADING
+  #ifdef _WIN32
+    #include <windows.h>
+    #undef EXTERN_C
+    #define AVISYNTH_LIB "avisynth"
+  #else
+    #include <dlfcn.h>
+    #if defined (__APPLE__)
+      #define AVISYNTH_LIB "libavxsynth.dylib"
+    #else
+      #define AVISYNTH_LIB "libavxsynth.so"
+    #endif /* __APPLE__ */
+
+    #define LoadLibrary(x) dlopen(x, RTLD_LAZY)
+    #define GetProcAddress dlsym
+    #define FreeLibrary dlclose
+  #endif /* _WIN32 */
+#endif /* CONFIG_DYNAMIC_LOADING */
+
 #if HAVE_PTHREADS || HAVE_W32THREADS || HAVE_OS2THREADS
 static int default_lockmgr_cb(void **arg, enum AVLockOp op)
 {
@@ -201,12 +220,13 @@ av_cold void avcodec_register(AVCodec *codec)
     p = last_avcodec;
     codec->next = NULL;
 
+    if (codec->init_static_data)
+        if (codec->init_static_data(codec))
+            return;
+
     while(*p || avpriv_atomic_ptr_cas((void * volatile *)p, NULL, codec))
         p = &(*p)->next;
     last_avcodec = &codec->next;
-
-    if (codec->init_static_data)
-        codec->init_static_data(codec);
 }
 
 #if FF_API_EMU_EDGE
@@ -3544,6 +3564,11 @@ void av_register_hwaccel(AVHWAccel *hwaccel)
 {
     AVHWAccel **p = last_hwaccel;
     hwaccel->next = NULL;
+
+    if (hwaccel->init_static_data)
+        if (hwaccel->init_static_data(hwaccel))
+            return;
+
     while(*p || avpriv_atomic_ptr_cas((void * volatile *)p, NULL, hwaccel))
         p = &(*p)->next;
     last_hwaccel = &hwaccel->next;
@@ -3799,3 +3824,71 @@ const uint8_t *avpriv_find_start_code(const uint8_t *av_restrict p,
 
     return p + 4;
 }
+
+int resolve_symbols(const char *library_name, void **dlhandle, FuncDef *func_defs) {
+    FuncDef *defs = func_defs;
+
+#if CONFIG_DYNAMIC_LOADING
+    char *error;
+
+    /*todo we need a usage counter to prevent unregistering when still in use*/
+    if (*dlhandle) {
+        av_log(NULL, AV_LOG_DEBUG, "Library %s already loaded\n", library_name);
+        return 0;
+    }
+
+    *dlhandle = LoadLibrary(library_name);
+    if (!*dlhandle) {
+        av_log(NULL, AV_LOG_DEBUG, "%s\n", dlerror());
+        return -1;
+    }
+    av_log(NULL, AV_LOG_DEBUG, "Library %s successfully loaded\n", library_name);
+
+    while (defs->func_name) {
+#ifndef _WIN32
+        dlerror(); /* Clear any existing error */
+#endif
+        *defs->dest_func_ptr = GetProcAddress(*dlhandle, defs->func_name);
+
+#ifdef _WIN32
+        if (!*defs->dest_func_ptr) {
+            error = [80];
+            snprintf(error, 80, "failed to resolve symbol %s", defs->func_name);
+        }
+#else
+        error = dlerror();
+#endif
+        if (error) {
+            av_log(NULL, AV_LOG_ERROR, "%s\n", error);
+            goto fail;
+        }
+	av_log(NULL, AV_LOG_DEBUG, "Symbol %s successfully resolved in library %s\n", defs->func_name, library_name);
+
+        defs++;
+    }
+    return 0;
+
+fail:
+    FreeLibrary(*dlhandle);
+    *dlhandle = NULL;
+
+    defs = func_defs;
+    while (defs->func_name) {
+        *defs->dest_func_ptr = NULL;
+        defs++;
+    }
+
+    return -1;
+
+#else
+    /* Note: in principle we could use dlopen() to resolve the symbols when
+     * the library is linked in but to support also platforms that don't have
+     * dlopen() we simply assign the function pointers instead.
+     */
+    while (defs->func_name) {
+        *defs->dest_func_ptr = defs->source_func_ptr;
+        defs++;
+    }
+    return 0;
+#endif /* CONFIG_DYNAMIC_LOADING */
+}
diff --git a/libavcodec/vaapi.c b/libavcodec/vaapi.c
index 15531e4..2cf85d7 100644
--- a/libavcodec/vaapi.c
+++ b/libavcodec/vaapi.c
@@ -30,12 +30,51 @@
  * @{
  */
 
+#define TOSTRING(x) #x
+#define STR(x) TOSTRING(x)
+#ifdef _WIN32
+#define LIBRARY_PREFIX
+#else
+#define LIBRARY_PREFIX lib
+#endif
+
+#define LIBRARY_SHORT_NAME va
+#define LIBRARY_NAME STR(LIBRARY_PREFIX) STR(LIBRARY_SHORT_NAME) SLIBSUF
+
+static struct VAAPISymbols {
+    void *dlhandle;
+
+    VAStatus (*vaDestroyBuffer)(VADisplay dpy, VABufferID buffer_id);
+    VAStatus (*vaUnmapBuffer)(VADisplay dpy, VABufferID buf_id);
+    VAStatus (*vaBeginPicture)(VADisplay dpy, VAContextID context, VASurfaceID render_target);
+    VAStatus (*vaRenderPicture)(VADisplay dpy, VAContextID context, VABufferID *buffers, int num_buffers);
+    VAStatus (*vaEndPicture)(VADisplay dpy, VAContextID context);
+    VAStatus (*vaCreateBuffer)(VADisplay dpy, VAContextID context, VABufferType type, unsigned int size,
+            unsigned int num_elements, void *data, VABufferID *buf_id);
+    VAStatus (*vaMapBuffer)(VADisplay dpy, VABufferID buf_id, void **pbuf);
+} VAAPISymbols;
+
+av_cold int init_static_data(AVHWAccel *hwaccel) {
+    struct FuncDef funcDefs[] = {
+            FUNC_DEF(VAAPISymbols, vaDestroyBuffer),
+            FUNC_DEF(VAAPISymbols, vaUnmapBuffer),
+            FUNC_DEF(VAAPISymbols, vaBeginPicture),
+            FUNC_DEF(VAAPISymbols, vaRenderPicture),
+            FUNC_DEF(VAAPISymbols, vaEndPicture),
+            FUNC_DEF(VAAPISymbols, vaCreateBuffer),
+            FUNC_DEF(VAAPISymbols, vaMapBuffer),
+            { NULL },
+    };
+
+    return resolve_symbols(LIBRARY_NAME, &VAAPISymbols.dlhandle, funcDefs);
+}
+
 static void destroy_buffers(VADisplay display, VABufferID *buffers, unsigned int n_buffers)
 {
     unsigned int i;
     for (i = 0; i < n_buffers; i++) {
         if (buffers[i]) {
-            vaDestroyBuffer(display, buffers[i]);
+            VAAPISymbols.vaDestroyBuffer(display, buffers[i]);
             buffers[i] = 0;
         }
     }
@@ -49,33 +88,33 @@ int ff_vaapi_render_picture(struct vaapi_context *vactx, VASurfaceID surface)
     if (!vactx->pic_param_buf_id)
         return 0;
 
-    vaUnmapBuffer(vactx->display, vactx->pic_param_buf_id);
+    VAAPISymbols.vaUnmapBuffer(vactx->display, vactx->pic_param_buf_id);
     va_buffers[n_va_buffers++] = vactx->pic_param_buf_id;
 
     if (vactx->iq_matrix_buf_id) {
-        vaUnmapBuffer(vactx->display, vactx->iq_matrix_buf_id);
+        VAAPISymbols.vaUnmapBuffer(vactx->display, vactx->iq_matrix_buf_id);
         va_buffers[n_va_buffers++] = vactx->iq_matrix_buf_id;
     }
 
     if (vactx->bitplane_buf_id) {
-        vaUnmapBuffer(vactx->display, vactx->bitplane_buf_id);
+        VAAPISymbols.vaUnmapBuffer(vactx->display, vactx->bitplane_buf_id);
         va_buffers[n_va_buffers++] = vactx->bitplane_buf_id;
     }
 
-    if (vaBeginPicture(vactx->display, vactx->context_id,
+    if (VAAPISymbols.vaBeginPicture(vactx->display, vactx->context_id,
                        surface) != VA_STATUS_SUCCESS)
         return -1;
 
-    if (vaRenderPicture(vactx->display, vactx->context_id,
+    if (VAAPISymbols.vaRenderPicture(vactx->display, vactx->context_id,
                         va_buffers, n_va_buffers) != VA_STATUS_SUCCESS)
         return -1;
 
-    if (vaRenderPicture(vactx->display, vactx->context_id,
+    if (VAAPISymbols.vaRenderPicture(vactx->display, vactx->context_id,
                         vactx->slice_buf_ids,
                         vactx->n_slice_buf_ids) != VA_STATUS_SUCCESS)
         return -1;
 
-    if (vaEndPicture(vactx->display, vactx->context_id) != VA_STATUS_SUCCESS)
+    if (VAAPISymbols.vaEndPicture(vactx->display, vactx->context_id) != VA_STATUS_SUCCESS)
         return -1;
 
     return 0;
@@ -98,7 +137,7 @@ int ff_vaapi_commit_slices(struct vaapi_context *vactx)
     vactx->slice_buf_ids = slice_buf_ids;
 
     slice_param_buf_id = 0;
-    if (vaCreateBuffer(vactx->display, vactx->context_id,
+    if (VAAPISymbols.vaCreateBuffer(vactx->display, vactx->context_id,
                        VASliceParameterBufferType,
                        vactx->slice_param_size,
                        vactx->slice_count, vactx->slice_params,
@@ -107,7 +146,7 @@ int ff_vaapi_commit_slices(struct vaapi_context *vactx)
     vactx->slice_count = 0;
 
     slice_data_buf_id = 0;
-    if (vaCreateBuffer(vactx->display, vactx->context_id,
+    if (VAAPISymbols.vaCreateBuffer(vactx->display, vactx->context_id,
                        VASliceDataBufferType,
                        vactx->slice_data_size,
                        1, (void *)vactx->slice_data,
@@ -126,9 +165,9 @@ static void *alloc_buffer(struct vaapi_context *vactx, int type, unsigned int si
     void *data = NULL;
 
     *buf_id = 0;
-    if (vaCreateBuffer(vactx->display, vactx->context_id,
+    if (VAAPISymbols.vaCreateBuffer(vactx->display, vactx->context_id,
                        type, size, 1, NULL, buf_id) == VA_STATUS_SUCCESS)
-        vaMapBuffer(vactx->display, *buf_id, &data);
+        VAAPISymbols.vaMapBuffer(vactx->display, *buf_id, &data);
 
     return data;
 }
diff --git a/libavcodec/vaapi_h264.c b/libavcodec/vaapi_h264.c
index 8eb8a66..8860c1a 100644
--- a/libavcodec/vaapi_h264.c
+++ b/libavcodec/vaapi_h264.c
@@ -356,6 +356,7 @@ AVHWAccel ff_h264_vaapi_hwaccel = {
     .type           = AVMEDIA_TYPE_VIDEO,
     .id             = AV_CODEC_ID_H264,
     .pix_fmt        = AV_PIX_FMT_VAAPI_VLD,
+    .init_static_data = init_static_data,
     .start_frame    = vaapi_h264_start_frame,
     .end_frame      = vaapi_h264_end_frame,
     .decode_slice   = vaapi_h264_decode_slice,
diff --git a/libavcodec/vaapi_internal.h b/libavcodec/vaapi_internal.h
index 918c718..8783a0d 100644
--- a/libavcodec/vaapi_internal.h
+++ b/libavcodec/vaapi_internal.h
@@ -35,6 +35,8 @@
  * @{
  */
 
+av_cold int init_static_data(AVHWAccel *hwaccel);
+
 /** Extract VASurfaceID from an AVFrame */
 static inline VASurfaceID ff_vaapi_get_surface_id(AVFrame *pic)
 {
diff --git a/libavcodec/vaapi_mpeg2.c b/libavcodec/vaapi_mpeg2.c
index 0d9059b..11ff207 100644
--- a/libavcodec/vaapi_mpeg2.c
+++ b/libavcodec/vaapi_mpeg2.c
@@ -138,6 +138,7 @@ AVHWAccel ff_mpeg2_vaapi_hwaccel = {
     .type           = AVMEDIA_TYPE_VIDEO,
     .id             = AV_CODEC_ID_MPEG2VIDEO,
     .pix_fmt        = AV_PIX_FMT_VAAPI_VLD,
+    .init_static_data = init_static_data,
     .start_frame    = vaapi_mpeg2_start_frame,
     .end_frame      = ff_vaapi_mpeg_end_frame,
     .decode_slice   = vaapi_mpeg2_decode_slice,
diff --git a/libavcodec/vaapi_vc1.c b/libavcodec/vaapi_vc1.c
index bba46d3..d1b0f5e 100644
--- a/libavcodec/vaapi_vc1.c
+++ b/libavcodec/vaapi_vc1.c
@@ -339,6 +339,7 @@ AVHWAccel ff_wmv3_vaapi_hwaccel = {
     .type           = AVMEDIA_TYPE_VIDEO,
     .id             = AV_CODEC_ID_WMV3,
     .pix_fmt        = AV_PIX_FMT_VAAPI_VLD,
+    .init_static_data = init_static_data,
     .start_frame    = vaapi_vc1_start_frame,
     .end_frame      = ff_vaapi_mpeg_end_frame,
     .decode_slice   = vaapi_vc1_decode_slice,
@@ -350,6 +351,7 @@ AVHWAccel ff_vc1_vaapi_hwaccel = {
     .type           = AVMEDIA_TYPE_VIDEO,
     .id             = AV_CODEC_ID_VC1,
     .pix_fmt        = AV_PIX_FMT_VAAPI_VLD,
+    .init_static_data = init_static_data,
     .start_frame    = vaapi_vc1_start_frame,
     .end_frame      = ff_vaapi_mpeg_end_frame,
     .decode_slice   = vaapi_vc1_decode_slice,
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Reply via email to