stuart at tropic.org.uk

F141, Department of Computing Science
University of Glasgow
Glasgow G12 8QQ
Cross-compiling JVLC for Windows

Note: Please don't email me about this page as I'm probably entirely unable to help. I haven't used JVLC for ages, and as such you are on your own.

This page details my experiences cross-compiling the Java bindings for VLC. The host machine was a Debian GNU/Linux box (etch), and the target was Win32. Some of this comes from the standard VLC cross-compilation instructions, some of it comes from the instructions for compiling JVLC and the rest comes from my own sweaty, bloody tears.

The main reason for doing this is because the binary distribution of JVLC for Win32 (found at http://phmorin.free.fr/jvlc-win32-060612.zip) does not include important functionality, such as arbitrary setPosition() and setTime() methods for Input objects (i.e., the video stream).

1. Firstly you need to get the relevant MinGW packages for Linux. On Debian these happen to be as follows

# apt-get install mingw32 mingw32-binutils mingw32-runtime

2. You will also need the VLC source code. I used version 0.8.6a. It may or may not work with other versions.

3. Get the latest additional pre-compiled libraries that you will need from http://download.videolan.org/pub/testing/win32/, and extract them using

# tar -xjf [.tar.bz2 contrib file] -C /

At this point you must make sure that you extract your files to the root (i.e., in the exact way shown above).

4. You'll need to now set up the Java environment. Your machine should have the latest SDK from Sun installed (e.g., in /usr/local/jdk) which will be henceforth referred to as $JAVA_HOME, and you will need access to a Windows version of the JDK as well. Firstly create symbolic links for java and javac

# ln -s $JAVA_HOME/bin/java $JAVA_HOME/bin/java.exe && ln -s $JAVA_HOME/bin/javac $JAVA_HOME/bin/javac.exe

(As a side note, in Debian it may be worth checking your /etc/alternatives/{java,javac} links to ensure they are pointing at the right place in $JAVA_HOME/bin.)

Next, copy the $JAVA_HOME\include\win32 directory and the $JAVA_HOME\lib\jawt.lib library from a Windows installation of the JDK and place them in their corresponding paths in your Linux JDK installation.

5. Use the following command to cross compile (adapted from the cross-compilation instructions for VLC, incidentally), which enables the Java bindings and the VLC media API (libvlc).

./bootstrap && \
 PKG_CONFIG_LIBDIR=/usr/win32/lib/pkgconfig \
 CPPFLAGS="-I/usr/win32/include -I/usr/win32/include/ebml" \
 LDFLAGS=-L/usr/win32/lib \
 CC=i586-mingw32msvc-gcc CXX=i586-mingw32msvc-g++ \
 ./configure --host=i586-mingw32msvc --build=i386-linux \
     --disable-gtk \
     --enable-nls --enable-sdl --with-sdl-config-path=/usr/win32/bin \
     --enable-ffmpeg --with-ffmpeg-mp3lame --with-ffmpeg-faac \
     --with-ffmpeg-zlib --enable-faad --enable-flac --enable-theora \
     --with-wx-config-path=/usr/win32/bin \
     --with-freetype-config-path=/usr/win32/bin \
     --with-fribidi-config-path=/usr/win32/bin \
     --enable-live555 --with-live555-tree=/usr/win32/live.com \
     --enable-caca --with-caca-config-path=/usr/win32/bin \
     --with-xml2-config-path=/usr/win32/bin \
     --with-dvdnav-config-path=/usr/win32/bin \
     --disable-cddax --disable-vcdx --enable-goom \
     --enable-twolame --enable-dvdread \
     --enable-debug --enable-java-bindings --enable-shared-libvlc

6. Now apply this patch in the dir root to fix some of the problems (temporarily)

vlc-0.8.6a # patch -p0 < jvlc_patches

7. Finally, call run compile (script) (or make) in the root directory, after which you should have VLC compiled along with the jvlc.dll library to be found in the bindings/java directory. Now package up VLC (make package-win32-zip) and all the relevant stuff from the bindings/java directory.

For a complete package you'll need the following:

You can download my own compiled version here (created 16/02/07). In order to compile and run the example, you'll need awt.dll and jawt.dll from a Windows Java distribution. Compiling and running the VLCExample.java file:

		
C:\jvlc_dist> javac -cp . VLCExample.java
C:\jvlc_dist> java -Djava.library.path=. -cp . VLCExample

The long-winded version

This section is mostly for indicating what kind of errors you might get in the compilation process and the solutions to them. This stuff follows from the steps 1-4 in the previous section.

After running step 5's command, I got the following

...
...
...
 BUILD   : vlc.exe
MAKE     : mozilla
MAKE     : bindings
MAKE     : mediacontrol-python
MAKE     : java
MAKE     : .
MAKE     : src
i586-mingw32msvc-g++ utils.cc -Wsign-compare -Wall  -mms-bitfields  -pipe 
-I. -Isrc -I../../ -I ../../include -I../../../include  
-I/usr/local/jdk1.5.0_01/include -I/usr/local/jdk1.5.0_01/include/win32 
`top_builddir=../../.. ../../../vlc-config --cflags pic` -c -o utils.o
i586-mingw32msvc-g++ video-jni.cc -Wsign-compare -Wall  -mms-bitfields  
-pipe -I. -Isrc -I../../ -I ../../include -I../../../include  
-I/usr/local/jdk1.5.0_01/include -I/usr/local/jdk1.5.0_01/include/win32 
`top_builddir=../../.. ../../../vlc-config --cflags pic` -c -o video-jni.o
video-jni.cc:32:31: ../includes/Video.h: No such file or directory
make: *** [all] Error 2

The JVLC instructions don't quite work at this point, since you have to actually go to the bindings/java directory and run make libjvlc.so, rather than just make The stuff in `Linker Option' on the JVLC instructions webpage is actually in the Java bindings Makefile already.

vlc-0.8.6a/bindings/java# make libjvlc.so
javac.exe org/videolan/jvlc/VLCException.java
javah org.videolan.jvlc.VLCException
javac.exe org/videolan/jvlc/Playlist.java
javah org.videolan.jvlc.Playlist
javac.exe org/videolan/jvlc/AudioIntf.java
javah org.videolan.jvlc.AudioIntf
javac.exe org/videolan/jvlc/Audio.java
javah org.videolan.jvlc.Audio
javac.exe org/videolan/jvlc/InputIntf.java
javah org.videolan.jvlc.InputIntf
javac.exe org/videolan/jvlc/Input.java
javah org.videolan.jvlc.Input
javac.exe org/videolan/jvlc/VideoIntf.java
javah org.videolan.jvlc.VideoIntf
javac.exe org/videolan/jvlc/Video.java
javah org.videolan.jvlc.Video
javac.exe org/videolan/jvlc/JLibVLC.java
javah org.videolan.jvlc.JLibVLC
javac.exe org/videolan/jvlc/JVLC.java
javah org.videolan.jvlc.JVLC
javac.exe org/videolan/jvlc/JVLCCanvas.java
javah org.videolan.jvlc.JVLCCanvas
javac.exe org/videolan/jvlc/JVLCPanel.java
javah org.videolan.jvlc.JVLCPanel
javac.exe org/videolan/jvlc/GenericVideoWidget.java
javah org.videolan.jvlc.GenericVideoWidget
make -C src
make[1]: Entering directory 
`/usr/local/src/vlc-0.8.6a/bindings/java/src'
i586-mingw32msvc-g++ utils.cc -Wsign-compare -Wall  -mms-bitfields  
-pipe -I. -Isrc -I../../ -I ../../include -I../../../include  
-I/usr/local/jdk1.5.0_01/include -I/usr/local/jdk1.5.0_01/include/win32 
`top_builddir=../../.. ../../../vlc-config --cflags pic` -c -o utils.o
i586-mingw32msvc-g++ video-jni.cc -Wsign-compare -Wall  -mms-bitfields  
-pipe -I. -Isrc -I../../ -I ../../include -I../../../include  
-I/usr/local/jdk1.5.0_01/include -I/usr/local/jdk1.5.0_01/include/win32 
`top_builddir=../../.. ../../../vlc-config --cflags pic` -c -o 
video-jni.o
video-jni.cc:32:31: ../includes/Video.h: No such file or directory
make[1]: *** [video-jni.o] Error 1
make[1]: Leaving directory 
`/usr/local/src/vlc-0.8.6a/bindings/java/src'
make: *** [libjvlc.so] Error 2

I copy those headers javah has just made to a new dir ./includes

vlc-0.8.6a/bindings/java/includes# mv ../*.h . && ls
org_videolan_jvlc_Audio.h               org_videolan_jvlc_JVLC.h
org_videolan_jvlc_AudioIntf.h           org_videolan_jvlc_JVLCPanel.h
org_videolan_jvlc_GenericVideoWidget.h  org_videolan_jvlc_Playlist.h
org_videolan_jvlc_Input.h               org_videolan_jvlc_Video.h
org_videolan_jvlc_InputIntf.h           org_videolan_jvlc_VideoIntf.h
org_videolan_jvlc_JLibVLC.h             org_videolan_jvlc_VLCException.h
org_videolan_jvlc_JVLCCanvas.h

and rename them to something the Makefile will recognise

vlc-0.8.6a/bindings/java/includes# for i 
in $(ls *.h); do mv $i `echo $i | cut -d "_" -f 4`; done
vlc-0.8.6a/bindings/java/includes# ls
Audio.h               Input.h      JVLCCanvas.h  Playlist.h   VLCException.h
AudioIntf.h           InputIntf.h  JVLC.h        Video.h
GenericVideoWidget.h  JLibVLC.h    JVLCPanel.h   VideoIntf.h

Now I try make libjvlc.so again

vlc-0.8.6a/bindings/java# make libjvlc.so
make -C src
make[1]: Entering directory 
`/usr/local/src/vlc-0.8.6a/bindings/java/src'
i586-mingw32msvc-g++ video-jni.cc -Wsign-compare -Wall  -mms-bitfields  
-pipe -I. -Isrc -I../../ -I ../../include -I../../../include  
-I/usr/local/jdk1.5.0_01/include -I/usr/local/jdk1.5.0_01/include/win32 
`top_builddir=../../.. ../../../vlc-config --cflags pic` -c -o 
video-jni.o
i586-mingw32msvc-g++ audio-jni.cc -Wsign-compare -Wall  -mms-bitfields  
-pipe -I. -Isrc -I../../ -I ../../include -I../../../include  
-I/usr/local/jdk1.5.0_01/include -I/usr/local/jdk1.5.0_01/include/win32 
`top_builddir=../../.. ../../../vlc-config --cflags pic` -c -o 
audio-jni.o
i586-mingw32msvc-g++ input-jni.cc -Wsign-compare -Wall  -mms-bitfields  
-pipe -I. -Isrc -I../../ -I ../../include -I../../../include  
-I/usr/local/jdk1.5.0_01/include -I/usr/local/jdk1.5.0_01/include/win32 
`top_builddir=../../.. ../../../vlc-config --cflags pic` -c -o 
input-jni.o
i586-mingw32msvc-g++ playlist-jni.cc -Wsign-compare -Wall  
-mms-bitfields  -pipe -I. -Isrc -I../../ -I ../../include 
-I../../../include  -I/usr/local/jdk1.5.0_01/include 
-I/usr/local/jdk1.5.0_01/include/win32 `top_builddir=../../.. 
../../../vlc-config --cflags pic` -c -o playlist-jni.o
playlist-jni.cc: In function `void 
Java_org_videolan_jvlc_Playlist__1stop(JNIEnv*, _jobject*)':
playlist-jni.cc:119: error: `usleep' was not declared in this scope
playlist-jni.cc:119: warning: unused variable 'usleep'
make[1]: *** [playlist-jni.o] Error 1
make[1]: Leaving directory 
`/usr/local/src/vlc-0.8.6a/bindings/java/src'
make: *** [libjvlc.so] Error 2

I fixed this with the following patch to playlist-jni.cc

--- src/playlist-jni.old.cc     2007-02-13 16:19:34.000000000 +0000
+++ src/playlist-jni.cc 2007-02-13 16:25:39.000000000 +0000
@@ -34,6 +34,12 @@

 #include "utils.h"

+#include 
+#ifdef usleep
+       #undef usleep
+#endif
+#define usleep(x) Sleep(1000 * (x))
+

 JNIEXPORT jint JNICALL Java_org_videolan_jvlc_Playlist__1playlist_1add 
(JNIEnv *env, jobject _this, jstring uri, jstring name,  jobjectArray 
options) {