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(-)

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;
     }
-- 
2.7.4 (Apple Git-66)

_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to