[FFmpeg-devel] FFmpeg for Mac

Neal Krawetz ffmpeg
Wed May 20 19:27:27 CEST 2009


Hi folks,

I managed to port FFMpeg to Macs as a Universal Binary (runs on both ppc
and x86 architectures).  There were a couple of changes that I needed
to make in order for this work.

I've tested this on the x86 architecture.  It compiles for a PPC, but I
have not tested it yet.  I suspect that it will fail because the ENDIAN
is hard-coded in config.h.

Anyway, here is my notes of things I needed to change for porting to the Mac:

* Install ffmpeg.
  Unforutnately, ffmpeg does not support universal binaries and configure
  does not set all of the configuration variables correctly.  So we will
  force it.
  Edit libavformat/framehook.c and comment out the header check:
        // #if HAVE_DLFCN_H
        #include <dlfcn.h>
        // #endif
  This header DOES exist when Xcode for MacOSX 10.5 is installed.
  Edit libavformat/rtpproto.c and comment out the header check:
        // #if HAVE_SYS_SELECT_H
        #include <sys/select.h>
        // #endif
  Edit ffserver.c and comment out the header check:
        // #if HAVE_DLFCN_H
        #include <dlfcn.h>
        // #endif
  Now compile:
    CFLAGS='-arch ppc -arch i386' ./configure --arch=x86
    CFLAGS='-arch ppc -arch i386' ./configure --arch=x86
    # Yes: Run configure twice! There is a permissions problem for config.h.
    make
    sudo make install
  This will install into /usr/local/.


As far as the endian issue goes, have you considered using a global
variable that sets the endian?  This would simplify portability.
Here's what my code (Piana) does since I have this same issue:

============================================
#ifndef BIG_ENDIAN
#define BIG_ENDIAN      4321
#endif
#ifndef LITTLE_ENDIAN
#define LITTLE_ENDIAN   1234
#endif

/* Set a global that everyone else will use */
int     PianaEndianHost=BIG_ENDIAN;     /* big/Intel ; little/Motorola */

/**********************************************
 PianaEndianSet(): Compute the endian for the host system.
 This must be called before running any of the other endian functions.
 **********************************************/
void    PianaEndianSet  ()
{
  byte Test[2] = {1,0};
  u_int16_t Num;
  Num = *(u_int16_t *)Test;
  if (Num == 1) PianaEndianHost=BIG_ENDIAN;
  else PianaEndianHost=LITTLE_ENDIAN;
} /* PianaEndianSet() */
============================================

Then all endian-specific code just needs to check this variable.
  if (JpegEndian == PianaEndianHost) ...
  else ...

When ffmpeg starts, the first thing it would do is set the endian flag.
The performance cost is a single if-condition.  (Three opcodes: load the
global, test the value, and jump on test.  And this could be reduced to
two opcodes if I used 0/1 instead of 1234/4321 like gcc defines.)

Using this test, the endian does not need to be hard-coded and ffmpeg can
be trivially cross-compiled without changing hard-coded header values that
were set by configure.

					-Neal
--
Neal Krawetz, Ph.D.
Hacker Factor Solutions
http://www.hackerfactor.com/
Author of "Introduction to Network Security" (Charles River Media, 2006)
and "Hacking Ubuntu" (Wiley, 2007)



More information about the ffmpeg-devel mailing list