[Ffmpeg-devel] [PATCH] Partial port of ffmpeg to MS Visual C - and a note on the inttypes.h issue

Yuri Vilmanis yuri
Thu Jan 25 09:04:54 CET 2007


This patch allows a small subset of the libavutil, libavcodec and 
libavformat libraries to be compiled using MSVC (specifically, the
mpeg-4 encoder and avi container format).

An overview of the motivation and process which led to this:
Requirement: to link an mpeg-4 (in avi) video encoder against a 64-bit
binary, to run on windows.
Software choice: There are many proprietary mpeg-4 encoders out there,
but they tend to be distributed binary only, and none advertise 64 bit
support. Chasing these various vendors down would take considerable
time, and gives us another software component out of our direct control.
ffmpeg gives us a viable solution in a reasonable time frame.
Problem: there is no gnu 64-bit tool chain for windows. "inttypes.h"
issues aside, if you want to link ffmpeg against a 64-bit executable for
Windows, you're S.O.L.
Solution: port selected features of ffmpeg to compile with the MS Visual
C compiler.

I don't remotely expect that any of this patch will make it onto the
ffmpeg mainline, or even be considered by the ffmpeg developers,
partially due to the intention of 'the ffmpeg project' not to support
non-gcc compilers, but mainly due to the general ugliness of the patch
(for example the conversion of elegant C99 struct and sparse array
initialization to very inelegant switch statements, accounting for the
MSVC 'near' keyword etc., generally throwing out inlining (this is
handled adequately by the optimiser anyway), and the fact that it only
addresses a small part of the codebase). However, it is presented here
to fulfil our civic duty and license agreements in distributing a
modified version, and in the hope that it will be useful (sic).

  -Yuri

P.S.
[ Disclaimer: The following is my (carefully referenced) personal
opinion and does not necessarily represent the position of my employer,
ISO, the FSF, the gcc project, microsoft, my cat (deceased) or any other
entity ]

Note: I'm taking 'ffmpeg' to mean ffmpeg and / or libavutil, libavcodec,
libavformat, or other components living in the ffmpeg source tree - but
mainly the libav* libraries. Please take no offence, this is merely an
act of notational convenience.

I've dredged through a couple of years of 'inttypes.h' flaming on the
ffmpeg-devel mailing list with some amusement... we have our own
'inttypes emulation' for exactly this kind of scenario, but removing the
requirement for inttypes.h when linking to a library is actually a good
idea. The following is not intended as a troll, designed to incite
violence, rekindle a flame war or anything of that nature, I'm simply
laying out some points in a (hopefully) more rational and better
referenced form than previous discussion on this list seems to have
reached. I'm not really pushing for this point of view to get adopted,
or really interested in engaging in lengthy discussion either; I have my
solution, and in the immortal words of some anonymous tester, it works
for me. On the other hand, I'm curious to see what comments people will
have...

First point:
MS Visual C / Visual C++ is not 'broken' in this respect. It is a
reasonably standards-compliant C++ compiler (yes, I am aware of areas
where it isn't, I have to code around them - occasionally), which can
also be operated as a C89 C compiler (known as "Visual C"). It's lack of
C99 support doesn't make it any less a C++ compiler, nor does it
generally affect its usefulness as a C compiler. Yes, the C99 standard
says "This second edition cancels and replaces the first edition", but
we all live in the real world, and full standards adoption takes time.
No-one's claiming gcc is a C99 compliant compiler either (those who beg
to differ, I refer you to the gcc project...), merely that it implements
some features from C99. MS Visual C's lack of support for C99 in C mode,
however, is moot, given the second point I wish to make...

Second point:
  From the presence of declarations such as

#ifdef __cplusplus
extern "C" {
#endif

in your public headers, I infer that you want to support linkage to
ffmpeg libraries (libav*) from C++ programs. (If this inference is
incorrect, feel free to ignore the following)

Discussion:
There is no requirement for a C++ compiler to supply C standard
libraries beyond what is specified in the C++ standard (not the C
standard, except where referenced)... with g++ just happen to be lucky
that gcc and its libraries are generally installed wherever g++ is, and
the standard library header lookup happens to find an inttypes.h ( by
the way, you actually want stdint.h for your typedefs here ) which looks
kinda C99 compatible (its not really even that - once again, refer to
the gcc project for details). Both ISO C++ 14882:1998 and ISO C++
14882:2003 specify a limited set of standard C headers which can be used
in C++, and in both cases, these headers are a subset of the C89
headers, and don't include inttypes.h, stdint.h, or any of the other new
headers introduced in C99.

Code which appears in an 'extern "C"{}' block (or anywhere else) in a
C++ header file is C++ code, not C code (just as the contents of an
'extern "F77" {}' block are C++, not Fortran), which happens to have C
linkage, i.e. uses C name mangling rather than C++ name mangling, and as
such allows (for practical purposes) function definitions to be linked
to binaries compiled from C source code which supply the implementation,
in whatever binary format(s) your particular platform and tools support
(how well this works depends on how closely your tool chain(s) agree on
mangling, of course - I've seen cases where this is a problem under
several platforms). Using the same set of headers for compiling with
libraries in C and C++ is common practice, however if you're doing this,
those headers should really be valid C++ as well as valid C.

At this point, and purely for my amusement, I'd like to request at this
point that one of the ffmpeg developers (I'll let whoever wishes to
claim that title use it) with a gnu bent argue that complete C99
(ISO/IEC 9899:1999) standard library support is required for a C++
compiler to be ISO C++ 14882:whatever compliant. Have fun... and don't
forget to refer to ISO C++ 14882 Annex C and Annex D.

Incidentally, FFMpeg uses the following C99 features which are marked as
broken or missing in gcc (see http://gcc.gnu.org/c99status.html) (these
I noted off-hand - there may be others):
  - variable-length arrays - support is not complete, and existing
support has not been tested against the C99 standard
  - extended integer types - stdint.h is marked missing, inttypes.h is
marked as having library issues (I gather this because it supplies the
typdefs which are meant to be in stdint.h - feel free to correct me here)
  - inline functions - broken (very): symbol exporting behaviour is the
exact opposite of the standard. Upshot is, anyone trying to use (compile
or link to) ffmpeg with a C99 compiler would appear to be in for a nasty
headache at link time (someone using a C99 compiler might like to
comment on this?).

Conclusions:
The "inttypes.h" problem is not a MS Visual C++ problem, it's a problem
with FFMpeg headers not being compatible with the ISO C++ standard. It
just happens to be a greater problem with Visual C++ because MS did not
go 'above and beyond' the C++ standard in the same way g++ has. Of
course, I'm not talking about people trying to link from C source code
using Visual C, those poor souls simply have an out-of-date C compiler
;), and should really use gcc - they could try a C99 compliant compiler,
but due to the inline function symbol exporting issue, this rare beast
would choke on ffmeg anyway. But you can't have everything...

If you really want to be that gnucentric, you could wrap all your public
headers in #ifdef __GNUC__ guards, and/or your 'extern "C"' C++ linkage
specifications should be wrapped in #ifdef __GNUG__ (yes, with __GNUC__
this would then be equivalent to __cplusplus, but its clearer as
__GNUG__), and perhaps even put in an #error if __GNUC__ is not defined.
Support for only gcc and none other is stated in the FAQ and elsewhere,
if you are really serious about this, the guards in your header files
should reflect it. This obviates the need to comply with any particular
standard, and instead ties the code to the gcc implementation. Which is
a perfectly valid approach. Just don't pretend you're necessarily
complying with the relevant ISO standards.

On the other hand, if you want to support linking to ffmpeg from
Standard C++, reliance on C99 standard library headers from your C++
public headers is right out. See ISO C++ 14882 Annex C.2 if you want to
know which standard C headers you can use in C++ code.

A third option is simply to drop support for C++ linkage - the 'pure C'
ffmpeg headers are then more or less C99 compliant (with a few
exceptions, e.g. inline functions, so the __GNUC__ guards are still a
god idea) and C++ standards compliance becomes a non-issue, so problem
solved. Of course, this may annoy some users (i.e. developers who link
to ffmpeg from C++ programs), but if ffmpeg really is developed solely
for the use of those with ffmpeg svn commit privileges - then those who
need Standard C++ linkage can have their commit privileges revoked, and
there is really no problem. Seriously though, from a practical point of
view, a standards-compliant C++ wrapper for ffmpeg could then be
developed as a separate project, leaving ffmpeg as pure C99 (more or
less) - not a pretty solution, but common enough (e.g. gtk vs gtk++).

Just my two c's (har har).
  -Yuri


-------------- next part --------------
A non-text attachment was scrubbed...
Name: ffmpeg_windows.diff.bz2
Type: application/octet-stream
Size: 43735 bytes
Desc: not available
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20070125/f2a30fda/attachment.obj>



More information about the ffmpeg-devel mailing list