Compiling WebM into FFMpeg for Windows

I have updated this post with a newer version of the VP8 patches to FFMpeg and support for libvorbis instead of the built in vorbis support.

Google has released source for the VP8 codec as the WebM project. The WebM project will be an open alternative in the HTML5 video tag codec space and being backed by Google, who will use it for YouTube, will give it a fighting chance. WebM is starting to be integrated into FFMpeg but there are still some patches that need to be applied. While there are some guides to how to build FFMpeg for Linux with VP8 WebM support I wanted to get it compiled for Windows.

First off this won't be done using a Windows install but instead using Virtual Box with a fresh install of Ubuntu 10.04 desktop. It is just faster and easier that way. So go ahead and grab Virtual Box and get Ubuntu installed on it before you continue.

I used this cross compiling X264 using Ubuntu as a base for part of my script. The entire script follows but if you want to make sure you get a good copy you can download it:

mkdir ffmpeg
cd ffmpeg


sudo apt-get install pkg-config yasm subversion cvs git-core gcc-mingw32

cat > << EOF
export CC=i586-mingw32msvc-gcc
export CXX=i586-mingw32msvc-g++
export CPP=i586-mingw32msvc-cpp
export AR=i586-mingw32msvc-ar
export RANLIB=i586-mingw32msvc-ranlib
export ADD2LINE=i586-mingw32msvc-addr2line
export AS=i586-mingw32msvc-as
export LD=i586-mingw32msvc-ld
export NM=i586-mingw32msvc-nm
export STRIP=i586-mingw32msvc-strip
export PATH="/usr/i586-mingw32msvc/bin:$PATH"
export PKG_CONFIG_PATH="$MINGBASE/lib/pkgconfig/"
exec "\$@"
chmod +x


cd $MINGBASE/src

wget -qO - | tar xzf -
cd libogg-1.2.0
$BASEDIR/ ./configure --enable-static --disable-shared --host=mingw32
DESTDIR=$MINGBASE make install prefix=
cd ..

wget -qO - | tar xzf -
cd libvorbis-1.3.1
LDFLAGS="-L$MINGBASE/lib" CFLAGS="-I$MINGBASE/include" $BASEDIR/ ./configure --enable-static --disable-shared --host=mingw32
DESTDIR=$MINGBASE make install prefix=
cd ..

wget -qO - | tar xzf -
cd pthreads-w32-2-8-0-release
make GC-static CROSS=i586-mingw32msvc-
cp libpthreadGC2.a $MINGBASE/lib
cp *.h $MINGBASE/include
cd ..

wget -qO - | tar xzf -
cd zlib-1.2.5/
$BASEDIR/ ./configure 
sed -i"" -e 's/-lc//' Makefile
DESTDIR=$MINGBASE make install prefix=
cd ..

git clone git://
cd libvpx/
git checkout fd0d7ff4c155b94d3f322addc7b66234b6908cc6
cat > /tmp/libvpx.x.patch << EOP 
diff -rupN libvpx.orig/configure libvpx/configure
--- libvpx.orig/configure	2010-07-11 14:49:18.703230816 -0400
+++ libvpx/configure	2010-07-11 14:50:33.747300030 -0400
@@ -436,9 +436,9 @@ process_detect() {
     check_header stdio.h || die "Unable to invoke compiler: \${CC} \${CFLAGS}"
-    check_ld <<EOF || die "Toolchain is unable to link executables"
-int main(void) {return 0;}
+#    check_ld <<EOF || die "Toolchain is unable to link executables"
+#int main(void) {return 0;}
     # check system headers
     check_header stdint.h
     check_header pthread.h
diff -rupN libvpx.orig/vp8/common/postproc.c libvpx/vp8/common/postproc.c
--- libvpx.orig/vp8/common/postproc.c	2010-07-11 14:49:18.939266476 -0400
+++ libvpx/vp8/common/postproc.c	2010-07-11 14:51:03.855300662 -0400
@@ -481,7 +481,7 @@ int vp8_post_proc_frame(VP8_COMMON *oci,
 #if ARCH_X86||ARCH_X86_64
-    vpx_reset_mmx_state();
+//    vpx_reset_mmx_state();
     if (flags & VP8D_DEMACROBLOCK)
diff -rupN libvpx.orig/vp8/common/systemdependent.h libvpx/vp8/common/systemdependent.h
--- libvpx.orig/vp8/common/systemdependent.h	2010-07-11 14:49:18.947263304 -0400
+++ libvpx/vp8/common/systemdependent.h	2010-07-11 14:51:25.019253115 -0400
@@ -10,12 +10,12 @@
 #include "vpx_ports/config.h"
-#if ARCH_X86 || ARCH_X86_64
-void vpx_reset_mmx_state(void);
-#define vp8_clear_system_state() vpx_reset_mmx_state()
+//#if ARCH_X86 || ARCH_X86_64
+//void vpx_reset_mmx_state(void);
+//#define vp8_clear_system_state() vpx_reset_mmx_state()
 #define vp8_clear_system_state()
 struct VP8Common;
 void vp8_machine_specific_config(struct VP8Common *);
patch -p1 < /tmp/libvpx.x.patch
$BASEDIR/ ./configure --disable-examples --disable-mmx --disable-sse --disable-sse2 --disable-sse3 --disable-ssse3
$BASEDIR/ make
DESTDIR=$MINGBASE make install prefix=/
cd ../..
mv usr/local/lib/* lib
mv usr/local/include/vpx/ include/
cd src

wget -qO - | zcat - > /tmp/ffmpeg-0.6_libvpx-0.9.1.diff
wget -qO - | tar xzf -
cd ffmpeg-0.6
patch -p0 < /tmp/ffmpeg-0.6_libvpx-0.9.1.diff

LDFLAGS="-L$MINGBASE/lib" CFLAGS="-I$MINGBASE/include" ./configure --target-os=mingw32 --cross-prefix=i586-mingw32msvc- --arch=x86 --prefix=$MINGBASE --enable-memalign-hack --enable-gpl --enable-avisynth --enable-version3 --enable-postproc --enable-libvpx --enable-runtime-cpudetect --disable-network --disable-devices --disable-encoder=vorbis --enable-libvorbis

cp ffmpeg.exe $BASEDIR

Just transfer that script to the user you create when you installed Ubuntu and run it. You will need to provide your password once so that the system can install a few tools but after that everything is done automatically. At the end you will have exe files in the directory you ran the script from.

Transfer the exe files that are created to a windows machine and then transcode a video like this:

ffmpeg.exe -i Big_Buck_Bunny_1080p.avi -acodec libvorbis -ac 2 -ab 128k -ar 44100 -s 720x480 Big_Buck_Bunny_1080p.webm

Please note that you need to include the audio codec information above to correctly encode the video. If you don't include rate values you will get an error telling you the libvorbis can't be initialized.

When the transcoding is done you will have a WebM video. Grab your closest HTML5 video player like VideoJS and you are ready to go.

For a demo video encoded using FFMpeg created with the above script check out this WebM demo video. You will need to use one of the following browsers to view the demo (all of these are as of July 13 2010, support will eventually be added to the main build):

I have tested the demo video on each of the above, except for IE9 that doesn't have WebM support as of yet, and it seems to work pretty well.

Leave a Reply

Your email address will not be published.