Video Live Wallpaper, Part 1
I took a freelance coding job asking me to code a Video Live Wallpaper. Sounds easy, right? Just create a Live Wallpaper and tell Android to play a video. How hard can that be? Unfortunately, in Android 2.1, 2.2, (and possibly 2.3), you can’t play videos in a Live Wallpaper. Well, you can but it’s something you have to program yourself. And that’s the problem. This seemingly trivial project is way harder than it looks. While not exactly rocket science, it’s not exactly a “walk in the park” either.
Let me explain exactly what’s involved: (1) you have to write your own decoder, which means that (2) you need to work with the NDK.
In this series, I’ll explain how I got video working in a Live Wallpaper using FFmpeg and OpenGL. The result is still a proof of concept but it’s more than enough to get you started.
We’re using FFmpeg because we are not writing our own video decoder. We could, but we shouldn’t. That’s poor programming practice.
- Download and install the NDK. If you’re working in the command line, add it to your
PATH. - Read an introductory tutorial for the NDK. This one is good. It’ll take you 5 minutes. Take a look at the Hello World app that comes with the NDK.
- Dowload FFmpeg. We’re going to use bambuser’s version for Android. Download
client version 1.3.7 to 1.3.10. That’s for NDK r5, which is what I used. - Unpack the bambuser archive into your
JNIfolder. (What’s the JNI folder? You did read the NDK tutorial, right?) - Extract the FFmpeg source code.
cdinto theffmpeg-androidfolder and runextrach.sh. - Modify
build.shfor your project. The first thing is to re-enable all the FFmpeg options. (By default, bambuser disables everything but one codec.) Secondly, add your package name using the-soname-prefix. (See the sample build file below).#!/bin/bash if [ "$NDK" = "" ]; then echo NDK variable not set, assuming ${HOME}/android-ndk export NDK=${HOME}/android-ndk fi SYSROOT=$NDK/platforms/android-3/arch-arm # Expand the prebuilt/* path into the correct one TOOLCHAIN=`echo $NDK/toolchains/arm-linux-androideabi-4.4.3/prebuilt/*-x86` export PATH=$TOOLCHAIN/bin:$PATH rm -rf build/ffmpeg mkdir -p build/ffmpeg cd ffmpeg # Don't build any neon version for now for version in armv5te armv7a; do DEST=../build/ffmpeg FLAGS="--target-os=linux --cross-prefix=arm-linux-androideabi- --arch=arm" FLAGS="$FLAGS --sysroot=$SYSROOT" FLAGS="$FLAGS --soname-prefix=/data/data/YOUR.PACKAGE.NAME/lib/" FLAGS="$FLAGS --enable-shared --disable-symver" FLAGS="$FLAGS --enable-small --optimization-flags=-O2" FLAGS="$FLAGS --enable-version3 --enable-nonfree" FLAGS="$FLAGS --disable-doc --disable-ffserver" case "$version" in neon) EXTRA_CFLAGS="-march=armv7-a -mfloat-abi=softfp -mfpu=neon" EXTRA_LDFLAGS="-Wl,--fix-cortex-a8" # Runtime choosing neon vs non-neon requires # renamed files ABI="armeabi-v7a" ;; armv7a) EXTRA_CFLAGS="-march=armv7-a -mfloat-abi=softfp" EXTRA_LDFLAGS="" ABI="armeabi-v7a" ;; *) EXTRA_CFLAGS="" EXTRA_LDFLAGS="" ABI="armeabi" ;; esac DEST="$DEST/$ABI" FLAGS="$FLAGS --prefix=$DEST" mkdir -p $DEST echo $FLAGS --extra-cflags="$EXTRA_CFLAGS" --extra-ldflags="$EXTRA_LDFLAGS" > $DEST/info.txt ./configure $FLAGS --extra-cflags="$EXTRA_CFLAGS" --extra-ldflags="$EXTRA_LDFLAGS" | tee $DEST/configuration.txt [ $PIPESTATUS == 0 ] || exit 1 make clean make -j4 || exit 1 make install || exit 1 done
Notes: (1) Run
./configure --helpfrom the command line for more options. (2) Make sure to enable the file protocol. You need that to open files on the phone. (3) I enabled the non-free codecs, which may or may not be compatible with the license for your project. (4) I’m not sure whether or not you need to add the package name to the libraries. I haven’t tested it out without the package name. - Compile FFmpeg. Run
build.shfrom the command line. - Go get some coffee. When you return you’ll have shared libraries (.so files) of FFmpeg. Why shared libraries and not static libraries? If I recall correctly, with NDK, you need to use shared libraries to build other modules.
- Add the libraries to the android project. Since you just compiled them, you need to add them as prebuilt shared libraries. This way you don’t recompile them each time you make changes to your NDK code. There are many ways to add these libraries to your project. Here’s one that works. Add this to the
Android.mkfile of the root JNI folder:
LOCAL_PATH := $(call my-dir) MY_LIB_PATH := ffmpeg-android/build/ffmpeg/armeabi/lib include $(CLEAR_VARS) LOCAL_MODULE := bambuser-libavcore LOCAL_SRC_FILES := $(MY_LIB_PATH)/libavcore.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := bambuser-libavformat LOCAL_SRC_FILES := $(MY_LIB_PATH)/libavformat.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := bambuser-libavcodec LOCAL_SRC_FILES := $(MY_LIB_PATH)/libavcodec.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := bambuser-libavdevice LOCAL_SRC_FILES := $(MY_LIB_PATH)/libavdevice.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := bambuser-libavfilter LOCAL_SRC_FILES := $(MY_LIB_PATH)/libavfilter.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := bambuser-libavutil LOCAL_SRC_FILES := $(MY_LIB_PATH)/libavutil.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := bambuser-libswscale LOCAL_SRC_FILES := $(MY_LIB_PATH)/libswscale.so include $(PREBUILT_SHARED_LIBRARY)
In the next part, we’ll actually do something with FFmpeg within Android.
UPDATE: To load a video from the SD card in FFmpeg, you need to use a file name of the form file:/sdcard/FILENAME.
About this entry
You’re currently reading “Video Live Wallpaper, Part 1,” an entry on Ikaruga 2
- Published:
- June 15, 2011 / 12:49 am
- Category:
- Technology
- Tags:
- Android, Linux, Live wallpaper, NDK, OpenGL
26 Comments
Jump to comment form | comment rss [?] | trackback uri [?]