Re: [FFmpeg-devel] [RFC] Support dynamic loading of third-party libs

2015-01-15 Thread Marc Giger
Hi Nicolas,

On Wed, 14 Jan 2015 21:33:25 +0100
Nicolas George geo...@nsup.org wrote:

 Le quintidi 25 nivôse, an CCXXIII, Marc Giger a écrit :
 For example if they want use libfaac then
  they should be able to do so without that much hassle a full
  compilation inclusive all dependencies can be.
 
 I was expecting something like that. Unfortunately, it does not work
 that way: dlopen()ing libfaac will not allow you to omit
 --enable-nonfree and to redistribute the resulting binary, because
 the libfaac wrapper still includes the faac headers, which contain
 non-trivial code (including a big structure definition) that get
 translated into the resulting object file.

That's a very good point. Never thought about it in this detail.
Given that fact I have to admin that dynamic loading makes
less sense. There may still be some usecases e.g. vaapi where it
would make sense, but this seems to be the minority.

 
 Apart from that, I fully agree with Michael's last comment: using
 dynamic linker black magic to make this lazy linking transparent is
 the best option to implement that feature if it is deemed useful.

libffi ?


Thanks for the clarification.

Marc


 
   On Linux/OpenSource OS's things
  are
  easy, on proprietary platforms ...
 
 Nothing prevents users on proprietary platforms from adopting
 automated repositories like Debian's apt system and everything that
 imitated it since to install Libre software, except the users'
 habits. Using such a repository to distribute your project is a good
 way of pushing users to change their habits for the better.
 
 Regards,
 
 -- 
   Nicolas George
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [RFC] Support dynamic loading of third-party libs

2015-01-14 Thread Marc Giger
Hi,

On Wed, 14 Jan 2015 10:49:23 +0100
wm4 nfx...@googlemail.com wrote:

 On Tue, 13 Jan 2015 19:45:01 +0100
 Marc Giger gigerst...@gmx.ch wrote:
 
  Hi,
  
  On Tue, 13 Jan 2015 14:54:33 +0100
  wm4 nfx...@googlemail.com wrote:
  
   On Mon, 12 Jan 2015 18:59:33 +0100
   Marc Giger gigerst...@gmx.ch wrote:
   
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?
   
   What's the point?
   
   Linux distros link everything anyway, they don't need to care.
  
  Gigix is not released yet ;-) and therefore I don't build a Linux
  distro myself but do still have interest in this feature...
  
   
   Other projects (distributing executables on windows etc.) restrict
   themselves to what they need anyway.
  
  That's my category and still have a demand for it...
 
 OK, but for what reason exactly?

Simply because I don't want to restrict users of what codecs
they have to use (I'm not the iXXX company and don't want to restrict
user wherever I can...). For example if they want use libfaac then
they should be able to do so without that much hassle a full compilation
inclusive all dependencies can be. On Linux/OpenSource OS's things are
easy, on proprietary platforms ...

In a perfect world, the user should be able to just click on the
download button and everything inclusive all codecs are magically
working. But since I don't live in a perfect world (e.g. Patent,
Licensing and License issues) I try to simplify things as much as I can
so that the user gets the best out of the box as possible. And if he
want's more he should be able to add that little piece without building
the whole thing.

I think it's a little bit comparable with the Linux Kernel.
Do you want to recompile the kernel and update the
bootloader everytime you plug-in a new device or need a firmware
update for a device? A good example is the nvidia driver. Because it
is proprietary it means it can't be redistributed with the Linux Kernel.
So when you need it you only need to compile the wrapper code and link
it against your kernel. No whole kernel rebuild needed not even a
reboot (maybe after you loaded the nvidia module ;-) ).

For example, I need about 10 to 15 minutes to compile and install a
new kernel, but it takes me 1 to 2 days to compile my whole project
inclusive ffmpeg and all libs on a windows system. And if I have to
setup the whole compiler toolchain, jdk and all other stuff that I
need it takes even a lot more time. If every user needs to do that just
because he needs codec xyz, good night... So dynamic loading would help
a lot.


 
   
   It also adds more global mutable state, which is not nice IMHO,
   although that's an implementation detail as used in your patch. A
  
  I'm open for better solutions. Please advice.
  
   library usage counter is maintained by dlopen/dlclose already, by
   the way.
  
  Yep, I'm aware of it. But look for example at the vaapi code then
  you will notice that the code is shared between multiple vaapi
  hwaccel's. If a deregister_hwaccel function will be implemented
  (makes most probably sense to be able to release the loaded lib) we
  need to take care that the function pointers are still valid as
  long as hwaccels are registered that uses the vaapi code. My
  intention was to memset to zero the function pointer struct when
  deregistering to prevent undeterministic behavior. Maybe a bad idea?
 
 You have two choices: 1. use a global table, and protect it with a
 mutex, plus your own usage counter if you want to use dlclose(), or 2.
 store the function table in each codec context (or whereever it's
 used), no need for a mutex or refcounting then.
 
 But still I wonder what's the purpose of this. libva and libmp3lame
 are not that big, and the mess resulting from having to duplicate
 much of the libs' headers makes maintenance harder. Is this going to
 be done for all external libs? Even a bigger mess.

I chose libva and libmp3lame at random. Yes, it was my intention to do
it for every external lib. If you ffmpeg-devs think that it is an
unnecessary feature and will result in a mess, then I'm absolutely fine
with this decision. All I wanted to know is how welcome such a
contribution is.

And if there is a chance that it will be accepted by you when it is
implemented properly, I'm willing to spend more time on it. Otherwise
we can stop the discussion here and I will use my time

Re: [FFmpeg-devel] [RFC] Support dynamic loading of third-party libs

2015-01-13 Thread Marc Giger
Hi Stephen,

On Tue, 13 Jan 2015 08:26:10 -0500
Stephen Hutchinson qyo...@gmail.com wrote:

 On general principle, the idea would be nice.  I'll leave broader
 critiques on the code to others, but I do have one thing to say:
 
 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)
  {
 
 What?
 
 One, that's a weird place to put a pruned-down version of the
 lib/header handler from libavformat/avisynth.c. And IMO, dynamic
 loading setup for a specific library belongs in that library's
 wrapper, since too much is liable to vary from library-to-library in
 what you need to be aware of.
 
 Two, AviSynth and AvxSynth are *always* dynamically loaded as it is.
 You cannot even build them as static (well, AvxSynth might be capable
 of that, but standard AviSynth is not, and currently, standard
 AviSynth can only be built by MSVC; good luck trying to link that
 against a MinGW-GCC built FFmpeg). Putting them inside this new block
 would be incorrect.
 
 Three, it changes the RTLD value once again?  It just got changed to
 RTLD_LOCAL a week or two ago.

Will have a look at this one.

 
 The loading block in libavofrmat/avisynth.c already handles the
 AviSynth case correctly.  It also has examples of how to deal with
 different versions, since it supports two different versions of
 AviSynth (2.5 and AvxSynth on one hand, and 2.6 and AviSynth+ on the
 other).
 
 I would generally recommend looking at how libavformat/avisynth.c is
 set up to get a feel for how to do this for other libraries, but the
 support for AviSynth using dynamic loading should not rely on other
 libraries doing so.  That's just not how AviSynth is intended to work.

Please ignore all of the avisynth stuff in my patch. It's a copypaste
error from myside. Sorry for the confusion...

 
 It would also possibly make sense to allow the user to specify a list
 of libs to dynamically load, just in case they want to use loading
 for some but not all.
 
 In essence,
 --enable-dynamic-loading would default to 'all', but the user could
 also do --enable-dynamic-loading=libname which would only activate it
 for X lib. 

I also thought about this one but for simplicity I left it away for the
moment. Will have a look at it when there is a consens about the basic
stuff.

Also many thanks to you for your valuable feedback!

Marc


___
 ffmpeg-devel mailing list
 ffmpeg-devel@ffmpeg.org
 http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


-- 
Lesson 1: Cryptographic protocols should not be developed by a
committee. -- Niels Ferguson and Bruce Schneier --
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [RFC] Support dynamic loading of third-party libs

2015-01-13 Thread Marc Giger
Hi Michael,


On Mon, 12 Jan 2015 22:57:35 +0100
Michael Niedermayer michae...@gmx.at wrote:

 On Mon, Jan 12, 2015 at 06:59:33PM +0100, Marc Giger wrote:
  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
 
 tested building 32bit binaries on 64bit linux:
 LD  ffmpeg_g
 /usr/bin/ld: cannot find -lva
 collect2: ld returned 1 exit status
 make: *** [ffmpeg_g] Error 1
 

Interesting...
replace my last point with
- only tested on Linux x86_64 with gcc 4.8.3 atm :-)

 
 
  - deregistering not implemented (dlclose)
  - versioning (which version of a lib should be loaded?)
  - library usage counter missing
  - ...?
  
 
  What do you think?
 
 I think binary based distros (and some of their users)
 might like this feature as it would allow them to build packages which
 have fewer hard dependencies but can still use all the libs if they
 are available and installed
 
 about the code, i think it looks ugly, too many #if too many changes
 interspaced with existing code. Could this be implemeted in a
 nicer way ?
 I am thinking here of keeping (almost) all changes
 outside of existing files

I totally agree. As I already noted the purpose of the patch is
to have basis for discussion and to get a feeling if such a feature
will be accepted by you ffmpeg-devs. In addition I wanted to discuss it
as early as possible so that you can point me in the right direction so
that everybody is happy in the end.

Many thanks for the valuable feedback!

Marc



 
 
 [...]
 
 -- 
 Michael GnuPG fingerprint:
 9FF2128B147EF6730BADF133611EC787040B0FAB
 
 Those who are too smart to engage in politics are punished by being
 governed by those who are dumber. -- Plato 


___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [RFC] Support dynamic loading of third-party libs

2015-01-12 Thread Marc Giger
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-grayenable 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 libilbcrequire 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