Message ID | 1468579396-35501-3-git-send-email-martin@martin.st |
---|---|
State | New |
Headers | show |
On Fri, Jul 15, 2016 at 01:43:16PM +0300, Martin Storsjö wrote: > This simplifies use of the patent license, simplifying use with a > library that has been downloaded at runtime (making it possible > to actually load and run libavcodec before the corresponding > OpenH264 library exists). > --- > This patch was sent for review earlier, and got some feedback, but it was > deferred back then due not knowing how much interest there would be in it > - see https://patches.libav.org/patch/56287/. > > Now there seems to be interest > in it, see https://lists.libav.org/pipermail/libav-devel/2016-July/078139.html, > so I'm resending it, with the feedback from the previous round applied, > and updated on top of the latest master. > --- > configure | 8 ++++-- > libavcodec/Makefile | 1 + > libavcodec/libopenh264.c | 4 +-- > libavcodec/libopenh264.h | 5 +++- > libavcodec/libopenh264dec.c | 61 ++++++++++++++++++++++++++++++++++++++++++--- > libavcodec/libopenh264enc.c | 49 +++++++++++++++++++++++++++++++++--- > 6 files changed, 115 insertions(+), 13 deletions(-) I'm undecided about the general merits of this patch. Some implementation remarks below... > --- a/configure > +++ b/configure > @@ -4594,6 +4596,8 @@ enabled libopencore_amrnb && require libopencore_amrnb opencore-amrnb/interf_dec > enabled libopencv && require_pkg_config opencv opencv/cv.h cvCreateImageHeader > enabled libopenh264 && require_pkg_config openh264 wels/codec_api.h WelsGetCodecVersion > +enabled libopenh264_dyn && { { check_header wels/codec_ver.h && enabled dyn_lib_open; } || > + die "ERROR: OpenH264 1.3 header not found, or dlopen/LoadLibrary not found"; } Not sure if mentioning the version number here is a good idea looking forward. > index 8eb7d36..f639ac5 100644 > --- a/libavcodec/Makefile > +++ b/libavcodec/Makefile > @@ -771,6 +771,7 @@ SKIPHEADERS += %_tablegen.h \ > SKIPHEADERS-$(CONFIG_D3D11VA) += d3d11va.h dxva2_internal.h > SKIPHEADERS-$(CONFIG_DXVA2) += dxva2.h dxva2_internal.h > SKIPHEADERS-$(CONFIG_LIBSCHROEDINGER) += libschroedinger.h > +SKIPHEADERS-$(CONFIG_LIBOPENH264) += libopenh264.h This will also skip the header if LIBOPENH264_DYN is set, which I think is not what you intend. > --- a/libavcodec/libopenh264dec.c > +++ b/libavcodec/libopenh264dec.c > @@ -23,6 +23,9 @@ > #include <wels/codec_ver.h> > > #include "libavutil/common.h" > +#if CONFIG_LIBOPENH264_DYN > +#include "libavutil/dyn_lib_open.h" > +#endif You are missing a config.h #include. > @@ -239,4 +291,5 @@ AVCodec ff_libopenh264_decoder = { > .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1, > .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS | FF_CODEC_CAP_INIT_THREADSAFE | > FF_CODEC_CAP_INIT_CLEANUP, > + .priv_class = &class, unrelated? > --- a/libavcodec/libopenh264enc.c > +++ b/libavcodec/libopenh264enc.c > @@ -24,6 +24,9 @@ > > #include "libavutil/attributes.h" > #include "libavutil/common.h" > +#if CONFIG_LIBOPENH264_DYN > +#include "libavutil/dyn_lib_open.h" > +#endif > #include "libavutil/opt.h" > #include "libavutil/internal.h" > #include "libavutil/intreadwrite.h" You're missing a config.h #include. > --- a/libavcodec/libopenh264dec.c > +++ b/libavcodec/libopenh264dec.c > @@ -67,15 +93,41 @@ static av_cold int svc_decode_init(AVCodecContext *avctx) > WelsTraceCallback callback_function; > + int (*create_func)(ISVCDecoder **ppDecoder); > + OpenH264Version (*get_version_func)(void); > + > +#if CONFIG_LIBOPENH264_DYN > + if (!s->libname) { > + av_log(avctx, AV_LOG_ERROR, "No library name provided\n"); > + return AVERROR(EINVAL); > + } > + s->lib = load_library(s->libname); > + if (!s->lib) { > + av_log(avctx, AV_LOG_ERROR, "Unable to load %s\n", s->libname); > + return AVERROR(EINVAL); > + } > +#endif > > - if ((err = ff_libopenh264_check_version(avctx)) < 0) > + if ((err = ff_libopenh264_check_version(avctx, get_version_func)) < 0) > return err; > > --- a/libavcodec/libopenh264enc.c > +++ b/libavcodec/libopenh264enc.c > @@ -97,11 +112,37 @@ static av_cold int svc_encode_init(AVCodecContext *avctx) > WelsTraceCallback callback_function; > AVCPBProperties *props; > + int (*create_func)(ISVCEncoder **ppEncoder); > + OpenH264Version (*get_version_func)(void); > + > +#if CONFIG_LIBOPENH264_DYN > + if (!s->libname) { > + av_log(avctx, AV_LOG_ERROR, "No library name provided\n"); > + return AVERROR(EINVAL); > + } > + s->lib = load_library(s->libname); > + if (!s->lib) { > + av_log(avctx, AV_LOG_ERROR, "Unable to load %s\n", s->libname); > + return AVERROR(EINVAL); > + } > +#endif > > - if ((err = ff_libopenh264_check_version(avctx)) < 0) > + if ((err = ff_libopenh264_check_version(avctx, get_version_func)) < 0) > return err; This looks similar enough that it could be shared between decoder and encoder. Diego
On Mon, 25 Jul 2016, Diego Biurrun wrote: > On Fri, Jul 15, 2016 at 01:43:16PM +0300, Martin Storsjö wrote: >> This simplifies use of the patent license, simplifying use with a >> library that has been downloaded at runtime (making it possible >> to actually load and run libavcodec before the corresponding >> OpenH264 library exists). >> --- >> This patch was sent for review earlier, and got some feedback, but it was >> deferred back then due not knowing how much interest there would be in it >> - see https://patches.libav.org/patch/56287/. >> >> Now there seems to be interest >> in it, see https://lists.libav.org/pipermail/libav-devel/2016-July/078139.html, >> so I'm resending it, with the feedback from the previous round applied, >> and updated on top of the latest master. >> --- >> configure | 8 ++++-- >> libavcodec/Makefile | 1 + >> libavcodec/libopenh264.c | 4 +-- >> libavcodec/libopenh264.h | 5 +++- >> libavcodec/libopenh264dec.c | 61 ++++++++++++++++++++++++++++++++++++++++++--- >> libavcodec/libopenh264enc.c | 49 +++++++++++++++++++++++++++++++++--- >> 6 files changed, 115 insertions(+), 13 deletions(-) > > I'm undecided about the general merits of this patch. > > Some implementation remarks below... > >> --- a/configure >> +++ b/configure >> @@ -4594,6 +4596,8 @@ enabled libopencore_amrnb && require libopencore_amrnb opencore-amrnb/interf_dec >> enabled libopencv && require_pkg_config opencv opencv/cv.h cvCreateImageHeader >> enabled libopenh264 && require_pkg_config openh264 wels/codec_api.h WelsGetCodecVersion >> +enabled libopenh264_dyn && { { check_header wels/codec_ver.h && enabled dyn_lib_open; } || >> + die "ERROR: OpenH264 1.3 header not found, or dlopen/LoadLibrary not found"; } > > Not sure if mentioning the version number here is a good idea looking > forward. Right, removed. >> index 8eb7d36..f639ac5 100644 >> --- a/libavcodec/Makefile >> +++ b/libavcodec/Makefile >> @@ -771,6 +771,7 @@ SKIPHEADERS += %_tablegen.h \ >> SKIPHEADERS-$(CONFIG_D3D11VA) += d3d11va.h dxva2_internal.h >> SKIPHEADERS-$(CONFIG_DXVA2) += dxva2.h dxva2_internal.h >> SKIPHEADERS-$(CONFIG_LIBSCHROEDINGER) += libschroedinger.h >> +SKIPHEADERS-$(CONFIG_LIBOPENH264) += libopenh264.h > > This will also skip the header if LIBOPENH264_DYN is set, which I think > is not what you intend. Hmm, indeed. Fixing that properly is a bit harder... >> --- a/libavcodec/libopenh264dec.c >> +++ b/libavcodec/libopenh264dec.c >> @@ -23,6 +23,9 @@ >> #include <wels/codec_ver.h> >> >> #include "libavutil/common.h" >> +#if CONFIG_LIBOPENH264_DYN >> +#include "libavutil/dyn_lib_open.h" >> +#endif > > You are missing a config.h #include. Sure >> @@ -239,4 +291,5 @@ AVCodec ff_libopenh264_decoder = { >> .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1, >> .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS | FF_CODEC_CAP_INIT_THREADSAFE | >> FF_CODEC_CAP_INIT_CLEANUP, >> + .priv_class = &class, > > unrelated? No, it's for hooking up the options (for setting the library name to load; previously the decoder wrapper didn't have any options). >> --- a/libavcodec/libopenh264enc.c >> +++ b/libavcodec/libopenh264enc.c >> @@ -24,6 +24,9 @@ >> >> #include "libavutil/attributes.h" >> #include "libavutil/common.h" >> +#if CONFIG_LIBOPENH264_DYN >> +#include "libavutil/dyn_lib_open.h" >> +#endif >> #include "libavutil/opt.h" >> #include "libavutil/internal.h" >> #include "libavutil/intreadwrite.h" > > You're missing a config.h #include. > >> --- a/libavcodec/libopenh264dec.c >> +++ b/libavcodec/libopenh264dec.c >> @@ -67,15 +93,41 @@ static av_cold int svc_decode_init(AVCodecContext *avctx) >> WelsTraceCallback callback_function; >> + int (*create_func)(ISVCDecoder **ppDecoder); >> + OpenH264Version (*get_version_func)(void); >> + >> +#if CONFIG_LIBOPENH264_DYN >> + if (!s->libname) { >> + av_log(avctx, AV_LOG_ERROR, "No library name provided\n"); >> + return AVERROR(EINVAL); >> + } >> + s->lib = load_library(s->libname); >> + if (!s->lib) { >> + av_log(avctx, AV_LOG_ERROR, "Unable to load %s\n", s->libname); >> + return AVERROR(EINVAL); >> + } >> +#endif >> >> - if ((err = ff_libopenh264_check_version(avctx)) < 0) >> + if ((err = ff_libopenh264_check_version(avctx, get_version_func)) < 0) >> return err; >> >> --- a/libavcodec/libopenh264enc.c >> +++ b/libavcodec/libopenh264enc.c >> @@ -97,11 +112,37 @@ static av_cold int svc_encode_init(AVCodecContext *avctx) >> WelsTraceCallback callback_function; >> AVCPBProperties *props; >> + int (*create_func)(ISVCEncoder **ppEncoder); >> + OpenH264Version (*get_version_func)(void); >> + >> +#if CONFIG_LIBOPENH264_DYN >> + if (!s->libname) { >> + av_log(avctx, AV_LOG_ERROR, "No library name provided\n"); >> + return AVERROR(EINVAL); >> + } >> + s->lib = load_library(s->libname); >> + if (!s->lib) { >> + av_log(avctx, AV_LOG_ERROR, "Unable to load %s\n", s->libname); >> + return AVERROR(EINVAL); >> + } >> +#endif >> >> - if ((err = ff_libopenh264_check_version(avctx)) < 0) >> + if ((err = ff_libopenh264_check_version(avctx, get_version_func)) < 0) >> return err; > > This looks similar enough that it could be shared between decoder and > encoder. No, I don't think it's really worth it, since it'd still end up something like this: #if CONFIG_LIBOPENH264_DYN if (load_library_ifdef_dyn_and_warn_if_not(s->libname)) return AVERROR(EINVAL); create_func = get_function() #endif You save a reused load_library call and error logging, nothing more, both which are trivial enough. // Martin
diff --git a/configure b/configure index ed32341..8dbc73b 100755 --- a/configure +++ b/configure @@ -204,6 +204,7 @@ External library support: --enable-libopencore-amrwb AMR-WB audio decoding --enable-libopencv computer vision --enable-libopenh264 H.264 video encoding/decoding + --enable-libopenh264-dyn H.264 video encoding/decoding via a dynamically loaded OpenH264 --enable-libopenjpeg JPEG 2000 image encoding/decoding --enable-libopus Opus audio encoding/decoding --enable-libpulse Pulseaudio sound server @@ -1254,6 +1255,7 @@ EXTERNAL_LIBRARY_LIST=" libopencore_amrwb libopencv libopenh264 + libopenh264_dyn libopenjpeg libopus libpulse @@ -2237,9 +2239,9 @@ libopencore_amrnb_decoder_deps="libopencore_amrnb" libopencore_amrnb_encoder_deps="libopencore_amrnb" libopencore_amrnb_encoder_select="audio_frame_queue" libopencore_amrwb_decoder_deps="libopencore_amrwb" -libopenh264_decoder_deps="libopenh264" +libopenh264_decoder_deps_any="libopenh264 libopenh264_dyn" libopenh264_decoder_select="h264_mp4toannexb_bsf" -libopenh264_encoder_deps="libopenh264" +libopenh264_encoder_deps_any="libopenh264 libopenh264_dyn" libopenjpeg_decoder_deps="libopenjpeg" libopenjpeg_encoder_deps="libopenjpeg" libopus_decoder_deps="libopus" @@ -4594,6 +4596,8 @@ enabled libopencore_amrnb && require libopencore_amrnb opencore-amrnb/interf_dec enabled libopencore_amrwb && require libopencore_amrwb opencore-amrwb/dec_if.h D_IF_init -lopencore-amrwb enabled libopencv && require_pkg_config opencv opencv/cv.h cvCreateImageHeader enabled libopenh264 && require_pkg_config openh264 wels/codec_api.h WelsGetCodecVersion +enabled libopenh264_dyn && { { check_header wels/codec_ver.h && enabled dyn_lib_open; } || + die "ERROR: OpenH264 1.3 header not found, or dlopen/LoadLibrary not found"; } enabled libopenjpeg && { { check_header openjpeg.h && check_lib2 openjpeg.h opj_version -lopenjpeg -DOPJ_STATIC; } || { require_pkg_config libopenjpeg1 openjpeg.h opj_version -DOPJ_STATIC; } } enabled libopus && require_pkg_config opus opus_multistream.h opus_multistream_decoder_create diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 8eb7d36..f639ac5 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -771,6 +771,7 @@ SKIPHEADERS += %_tablegen.h \ SKIPHEADERS-$(CONFIG_D3D11VA) += d3d11va.h dxva2_internal.h SKIPHEADERS-$(CONFIG_DXVA2) += dxva2.h dxva2_internal.h SKIPHEADERS-$(CONFIG_LIBSCHROEDINGER) += libschroedinger.h +SKIPHEADERS-$(CONFIG_LIBOPENH264) += libopenh264.h SKIPHEADERS-$(CONFIG_LIBVPX) += libvpx.h SKIPHEADERS-$(CONFIG_MPEG_XVMC_DECODER) += xvmc.h SKIPHEADERS-$(CONFIG_NVENC) += nvenc.h diff --git a/libavcodec/libopenh264.c b/libavcodec/libopenh264.c index 6252cfd..77bac8e 100644 --- a/libavcodec/libopenh264.c +++ b/libavcodec/libopenh264.c @@ -46,13 +46,13 @@ void ff_libopenh264_trace_callback(void *ctx, int level, const char *msg) av_log(ctx, equiv_libav_log_level, "%s\n", msg); } -int ff_libopenh264_check_version(void *logctx) +int ff_libopenh264_check_version(void *logctx, OpenH264Version (*get_version_func)(void)) { // Mingw GCC < 4.7 on x86_32 uses an incorrect/buggy ABI for the WelsGetCodecVersion // function (for functions returning larger structs), thus skip the check in those // configurations. #if !defined(_WIN32) || !defined(__GNUC__) || !ARCH_X86_32 || AV_GCC_VERSION_AT_LEAST(4, 7) - OpenH264Version libver = WelsGetCodecVersion(); + OpenH264Version libver = get_version_func(); if (memcmp(&libver, &g_stCodecVersion, sizeof(libver))) { av_log(logctx, AV_LOG_ERROR, "Incorrect library version loaded\n"); return AVERROR(EINVAL); diff --git a/libavcodec/libopenh264.h b/libavcodec/libopenh264.h index 7c69481..865cb00 100644 --- a/libavcodec/libopenh264.h +++ b/libavcodec/libopenh264.h @@ -22,6 +22,9 @@ #ifndef AVCODEC_LIBOPENH264_H #define AVCODEC_LIBOPENH264_H +#include <wels/codec_api.h> +#include <wels/codec_ver.h> + #define OPENH264_VER_AT_LEAST(maj, min) \ ((OPENH264_MAJOR > (maj)) || \ (OPENH264_MAJOR == (maj) && OPENH264_MINOR >= (min))) @@ -34,6 +37,6 @@ void ff_libopenh264_trace_callback(void *ctx, int level, const char *msg); -int ff_libopenh264_check_version(void *logctx); +int ff_libopenh264_check_version(void *logctx, OpenH264Version (*get_version_func)(void)); #endif /* AVCODEC_LIBOPENH264_H */ diff --git a/libavcodec/libopenh264dec.c b/libavcodec/libopenh264dec.c index cc18f24..6f45782 100644 --- a/libavcodec/libopenh264dec.c +++ b/libavcodec/libopenh264dec.c @@ -23,6 +23,9 @@ #include <wels/codec_ver.h> #include "libavutil/common.h" +#if CONFIG_LIBOPENH264_DYN +#include "libavutil/dyn_lib_open.h" +#endif #include "libavutil/fifo.h" #include "libavutil/imgutils.h" #include "libavutil/intreadwrite.h" @@ -34,19 +37,38 @@ #include "libopenh264.h" typedef struct SVCContext { + const AVClass *av_class; +#if CONFIG_LIBOPENH264_DYN + const char *libname; + void *lib; +#endif + void (*destroy_func)(ISVCDecoder *ppDecoder); ISVCDecoder *decoder; AVBSFContext *bsf; AVFifoBuffer *packet_fifo; AVPacket pkt_filtered; } SVCContext; +#define OFFSET(x) offsetof(SVCContext, x) +#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM +static const AVOption options[] = { +#if CONFIG_LIBOPENH264_DYN + { "openh264lib", "OpenH264 library name", OFFSET(libname), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VD }, +#endif + { NULL } +}; + +static const AVClass class = { + "libopenh264dec", av_default_item_name, options, LIBAVUTIL_VERSION_INT +}; + static av_cold int svc_decode_close(AVCodecContext *avctx) { SVCContext *s = avctx->priv_data; AVPacket pkt; - if (s->decoder) - WelsDestroyDecoder(s->decoder); + if (s->decoder && s->destroy_func) + s->destroy_func(s->decoder); while (s->packet_fifo && av_fifo_size(s->packet_fifo) >= sizeof(pkt)) { av_fifo_generic_read(s->packet_fifo, &pkt, sizeof(pkt), NULL); @@ -56,6 +78,10 @@ static av_cold int svc_decode_close(AVCodecContext *avctx) av_bsf_free(&s->bsf); av_packet_unref(&s->pkt_filtered); av_fifo_free(s->packet_fifo); +#if CONFIG_LIBOPENH264_DYN + if (s->lib) + free_library(s->lib); +#endif return 0; } @@ -67,15 +93,41 @@ static av_cold int svc_decode_init(AVCodecContext *avctx) int err; int log_level; WelsTraceCallback callback_function; + int (*create_func)(ISVCDecoder **ppDecoder); + OpenH264Version (*get_version_func)(void); + +#if CONFIG_LIBOPENH264_DYN + if (!s->libname) { + av_log(avctx, AV_LOG_ERROR, "No library name provided\n"); + return AVERROR(EINVAL); + } + s->lib = load_library(s->libname); + if (!s->lib) { + av_log(avctx, AV_LOG_ERROR, "Unable to load %s\n", s->libname); + return AVERROR(EINVAL); + } + create_func = (void*) get_function(s->lib, "WelsCreateDecoder"); + s->destroy_func = (void*) get_function(s->lib, "WelsDestroyDecoder"); + get_version_func = (void*) get_function(s->lib, "WelsGetCodecVersion"); + + if (!create_func || !s->destroy_func || !get_version_func) { + av_log(avctx, AV_LOG_ERROR, "%s doesn't contain the necessary functions\n", s->libname); + return AVERROR(EINVAL); + } +#else + create_func = WelsCreateDecoder; + get_version_func = WelsGetCodecVersion; + s->destroy_func = WelsDestroyDecoder; +#endif - if ((err = ff_libopenh264_check_version(avctx)) < 0) + if ((err = ff_libopenh264_check_version(avctx, get_version_func)) < 0) return err; s->packet_fifo = av_fifo_alloc(sizeof(AVPacket)); if (!s->packet_fifo) return AVERROR(ENOMEM); - if (WelsCreateDecoder(&s->decoder)) { + if (create_func(&s->decoder)) { av_log(avctx, AV_LOG_ERROR, "Unable to create decoder\n"); return AVERROR_UNKNOWN; } @@ -239,4 +291,5 @@ AVCodec ff_libopenh264_decoder = { .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS | FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, + .priv_class = &class, }; diff --git a/libavcodec/libopenh264enc.c b/libavcodec/libopenh264enc.c index a09b7cf..1d67fdb 100644 --- a/libavcodec/libopenh264enc.c +++ b/libavcodec/libopenh264enc.c @@ -24,6 +24,9 @@ #include "libavutil/attributes.h" #include "libavutil/common.h" +#if CONFIG_LIBOPENH264_DYN +#include "libavutil/dyn_lib_open.h" +#endif #include "libavutil/opt.h" #include "libavutil/internal.h" #include "libavutil/intreadwrite.h" @@ -39,6 +42,11 @@ typedef struct SVCContext { const AVClass *av_class; +#if CONFIG_LIBOPENH264_DYN + const char *libname; + void *lib; +#endif + void (*destroy_func)(ISVCEncoder *ppEncoder); ISVCEncoder *encoder; int slice_mode; int loopfilter; @@ -52,6 +60,9 @@ typedef struct SVCContext { #define OFFSET(x) offsetof(SVCContext, x) #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { +#if CONFIG_LIBOPENH264_DYN + { "openh264lib", "OpenH264 library name", OFFSET(libname), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE }, +#endif #if OPENH264_VER_AT_LEAST(1, 6) { "slice_mode", "Slice mode", OFFSET(slice_mode), AV_OPT_TYPE_INT, { .i64 = SM_FIXEDSLCNUM_SLICE }, SM_SINGLE_SLICE, SM_RESERVED, VE, "slice_mode" }, #else @@ -82,10 +93,14 @@ static av_cold int svc_encode_close(AVCodecContext *avctx) { SVCContext *s = avctx->priv_data; - if (s->encoder) - WelsDestroySVCEncoder(s->encoder); + if (s->encoder && s->destroy_func) + s->destroy_func(s->encoder); if (s->skipped > 0) av_log(avctx, AV_LOG_WARNING, "%d frames skipped\n", s->skipped); +#if CONFIG_LIBOPENH264_DYN + if (s->lib) + free_library(s->lib); +#endif return 0; } @@ -97,11 +112,37 @@ static av_cold int svc_encode_init(AVCodecContext *avctx) int log_level; WelsTraceCallback callback_function; AVCPBProperties *props; + int (*create_func)(ISVCEncoder **ppEncoder); + OpenH264Version (*get_version_func)(void); + +#if CONFIG_LIBOPENH264_DYN + if (!s->libname) { + av_log(avctx, AV_LOG_ERROR, "No library name provided\n"); + return AVERROR(EINVAL); + } + s->lib = load_library(s->libname); + if (!s->lib) { + av_log(avctx, AV_LOG_ERROR, "Unable to load %s\n", s->libname); + return AVERROR(EINVAL); + } + create_func = (void*) get_function(s->lib, "WelsCreateSVCEncoder"); + s->destroy_func = (void*) get_function(s->lib, "WelsDestroySVCEncoder"); + get_version_func = (void*) get_function(s->lib, "WelsGetCodecVersion"); + + if (!create_func || !s->destroy_func || !get_version_func) { + av_log(avctx, AV_LOG_ERROR, "%s doesn't contain the necessary functions\n", s->libname); + return AVERROR(EINVAL); + } +#else + create_func = WelsCreateSVCEncoder; + get_version_func = WelsGetCodecVersion; + s->destroy_func = WelsDestroySVCEncoder; +#endif - if ((err = ff_libopenh264_check_version(avctx)) < 0) + if ((err = ff_libopenh264_check_version(avctx, get_version_func)) < 0) return err; - if (WelsCreateSVCEncoder(&s->encoder)) { + if (create_func(&s->encoder)) { av_log(avctx, AV_LOG_ERROR, "Unable to create encoder\n"); return AVERROR_UNKNOWN; }