[FFmpeg-devel] On in-tree external headers

Stephen Hutchinson qyot27 at gmail.com
Tue Oct 31 03:06:35 EET 2017

On 10/30/2017 4:16 PM, Jan Ekstrom wrote:
> On Mon, Oct 30, 2017 at 9:51 PM, Mark Thompson <sw at jkqxz.net> wrote:
>> PPS:
>> The position stated above would imply removing the avisynth headers.  Can anyone who uses it comment on what would be required for that?
> Avisynth headers are available from the Avisynth SDK that comes with
> each installer of Avisynth. The reason why some projects made their
> own forks of the header is because of the useful features added during
> the (rather long) development phase of the 2.6 release, during which
> the GPL exceptions regarding the header were removed. And thus people
> re-implemented them basing on the 2.5.8 stable header. Not sure if the
> GPL exceptions were re-instated with the final release of Avisynth
> 2.6, and what is the status with the headers that come with the
> Avisynth+ project. In any case, the headers are readily available from
> various places.
> Otherwise the only difference with the included header would be
> Avxsynth compatibility? Which is quite a bit less used than original
> Avisynth on wine, or Vapoursynth natively on *nix at this point. It
> was one of those things where a company forked an old version of a
> project and made it compile on *nix, while most of the plugins etc
> were quite Windows-specific. The project still does exist and is
> available, though.

The short version: it's a mess.  The slightly longer version:
there's a regression in the current version of the AviSynth+
headers that would mean requiring users to jump through some
additional hoops.

The flimsiest argument would be that AviSynth support, from the
time the first demuxer was added in 2006, was always just a
simple --enable-avisynth and it just worked.  The first demuxer
didn't require external headers (because it was accessed via VfW),
so to preserve the behavior behind --enable-avisynth (and for
reasons I detail below), the correct headers were included in

AviSynth has two different API interfaces: the C++ interface as
implemented in avisynth.h, and the C interface as implemented in
avisynth_c.h.  FFmpeg's support of AviSynth (and x264's) use the
C interface header.

The licensing mess that occurred during AviSynth 2.6's development
only affected the C++ header: the GPL exception was never taken
out of avisynth_c.h, but upstream AviSynth 2.6 also never added
equal features to the C header until late in 2.6's dev cycle (the
proper non-alpha/beta/RC release of 2.6 didn't occur until May 2016,
and yes, by that point the GPL exception had been added back to the
C++ header). This meant that in 2011(?), when x264 wanted to add support
for 2.6's additional pixel formats (YV16/yuv422p, YV24/yuv444p), it
needed to ship a modified version of avisynth_c.h that didn't exist

When the AviSynth demuxer in libavformat was rewritten in 2012-2013,
it used x264's forked headers.  In both x264's and FFmpeg's cases,
the local copies of the headers were provided so that users wouldn't
have to manually copy the headers around and hope they get the right
one (since 2.5's headers would not work correctly with the addition
of yuv422p, yuv444p, and gray).  AvxSynth's were included mostly so that 
the inclusion behavior is the same - AviSynth as a Windows project is
MSVC-specific and didn't have a standard installation Makefile for
cross-compiling in its source tree, so the easiest way to ensure users
grabbed the correct header was by putting them in compat.

AviSynth+ altered this dynamic in some ways.  Notably, AviSynth+ 
supports *tons* of new pixfmts (support for these was added to FFmpeg
in 2016, for the most part), and it also includes a GNUmakefile so
that the headers can be installed under a normal FHS directory
structure.  And AviSynth+ did integrate the compatible changes from
2.6's RCs and Final releases, including the restoration of the GPL
exception to the C++ header - so the licensing for AviSynth+'s headers
is the same as classic AviSynth 2.6.

But there's another problem now: AviSynth+'s source was made compliant 
with MinGW-w64 and GCC in August/September 2016, but the changes to the
capi.h header made 32-bit MSVC builds of the library incompatible
with a program built with GCC, like most times when building FFmpeg.
I never attempted to see if the newer capi.h allowed MSVC-built
AviSynth.dll to work with MSVC-built FFmpeg, but that's not a workable
solution because the AviSynth demuxer doesn't link AviSynth.dll to
FFmpeg, it dynamically loads the library through the dlopen compat
(dynamic loading is also the AviSynth-approved way of using the
library), and it still screws over those of us that cross-compile
FFmpeg for win32 with MinGW-w64 and GCC.

Since capi.h in upstream AviSynth+ causes that mess, using the
GNUmakefile in AviSynth+'s source tree will get you technically
wrong headers unless you do a git checkout first.  It would mean
FFmpeg would fall into the same trap Libav did, since they've always
required AviSynth's headers to be installed to the system rather
than provided in compat/.  If you look at their documentation it 
explicitly states which revision should be checked out.  Building
against HEAD does work with GCC-built 32-bit AviSynth.dll, but causes 
GCC-built 32-bit Libav to reject MSVC-built 32-bit AviSynth.dll
(which is the most important and common case, since GCC support is
still technically experimental).  This causes additional issues,
since GCC builds of AviSynth+ can't use plugins using the C++
interface, which is most plugins for AviSynth, and why GCC support
is still considered experimental.  Using AviSynth+'s HEAD copies
of its headers would cause the same problem for FFmpeg.

I tried to figure out some way to allow all four cases to work
correctly in AviSynth+'s capi.h header, but I didn't get anywhere.
Furthermore, the kludge-y ifdeffery I added to capi.h that got
everything except 32-bit GCC builds to play nice doesn't have
an easy path to get into upstream AviSynth+¹ because of ultim (the repo
owner) going on hiatus, and so the effective development HEAD
of AviSynth+ is actually pinterf's repo² for the time being. That
kind of uncertainty is unwieldy, to say the least.

Speaking as the maintainer of the AviSynth demuxer, the AvxSynth
support has an expiration date, but it's contingent upon AviSynth+
properly going cross-platform.  Some attempts at this were started
a couple years ago, but stalled (and probably need to be re-done
at this point, given the changes to be compliant with MinGW-w64).
The end goal is to have AviSynth+ working natively on Linux and OSX,
rendering the special-casing for AvxSynth completely irrelevant.
It would also mean that there would be no reason at that point to
continue having the headers in compat/, but IMO the situation is
still way too convoluted for that.

¹https://github.com/AviSynth/AviSynthPlus.git ('MT' is the dev HEAD)
²https://github.com/pinterf/AviSynthPlus.git (ditto)

More information about the ffmpeg-devel mailing list