Technology

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.

  1. Download and install the NDK. If you’re working in the command line, add it to your PATH.
  2. 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.
  3. 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.
  4. Unpack the bambuser archive into your JNI folder. (What’s the JNI folder? You did read the NDK tutorial, right?)
  5. Extract the FFmpeg source code. cd into the ffmpeg-android folder and run extrach.sh.
  6. Modify build.sh for 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 --help from 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.

  7. Compile FFmpeg. Run build.sh from the command line.
  8. 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.
  9. 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.mk file 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 these ads
Standard

27 thoughts on “Video Live Wallpaper, Part 1

  1. Pingback: Video Live Wallpaper, Part 2 « Ikaruga 2

  2. Pingback: Video Live Wallpaper, Part 3 « Ikaruga 2

  3. Pingback: Video Live Wallpaper, Part 4 « Ikaruga 2

  4. Tristus1er says:

    I have tryed on Windows : compilation fail :
    C compiler test failed.
    I have installed Linux : more problems :
    –soname-prefix : parameter unknown
    –optimization-flags : parameter unknown
    and then the same message :
    C compiler test failed.
    I have created a tmp folder in the source folder (seen on some forum), installed build-essential, but nothing work.
    I have tried to use the precompiled libraries … but impossible to compile le las one (video.c).
    I have seen that many people has problems to compile ffmpeg, your tutorial is very nice, so maybe it would be a nice place to explain how to fix all the possible problems here ?
    Thank you.

    • How are you compiling video.c? Just to be clear and I just noticed that these instructions aren’t, you have to: (1) compile FFmpeg using the build script shown here, (2) run “ndk-build” from the project root directory. I just did that and everything compiled fine.

  5. Costa says:

    Is it possible to compile FFmpeg in windows ? I can develop no problem – invoke NDK-BUILD from android-ndk-r7 for Windows – but I come up short when trying to compile FFmpeg through Cygwin.
    /ffmpeg/config.log always list some sporadic “No such file or directory” followed by “no input files” “C compiler test failed” no matter the workaround I find for each error.
    Is there any way to avoid these problems ?
    Thanks.

    config.log example:

    type mktemp
    mktemp is /usr/bin/mktemp
    check_ld
    check_cc
    BEGIN /tmp/ffconf.m5aXwDgN.c
    1 int main(void){ return 0; }
    END /tmp/ffconf.m5aXwDgN.c
    arm-linux-androideabi-gcc –sysroot=/cygdrive/c/Android/android-ndk-r7/platforms/android-3/arch-arm -c -o /tmp/ffconf.34Ny9Kgu.o /tmp/ffconf.m5aXwDgN.c
    arm-linux-androideabi-gcc.exe: /tmp/ffconf.m5aXwDgN.c: No such file or directory

    arm-linux-androideabi-gcc.exe: no input files

    C compiler test failed.

  6. Tristus1er says:

    @ikaruga2099 => Thanks for your help
    @Costa => I have tryed under windows … it was too hard for me … I have installed a virtual machine running Ubuntu and it’s was better thanks to this great tutorial :-D
    So I run windows, and I can compile ffmpeg.

    For me it’s the best way to do if running under windows.

    • Tristus1er says:

      Hello zelizeliOri
      If you need some help about the customisation of this code, I might help you.
      Please let me your email, and I’ll contact you.

      Best regards.

    • Ravi says:

      hi i’m making use of your code live video livewallpaper sample
      nut i’m getting error
      im usinf windows xp
      cygwin

      pls help

      Sorry for my engilish

  7. Pingback: Change color-depth in FFMpeg

  8. Marcelo says:

    Hi Guys, I would like to know if has some tutorial to show how create a video from image using ffmpeg + Android…

    • Not sure exactly what you mean by that. You can to take some images, then turn them into a video? I’m assuming you want to create an app with that functionality. If I recall, ffmpeg does have that functionality. Search for the C code then call it via the NDK using this as a base.

  9. Vishal says:

    Nice document.

    THANKS ikaruga2099.

    I have successfully run the Video as Live wallpaper. I used Ubuntu to build the app.

    I seen the below issues :
    1. The wallpaper set to black screen on HTC Desire (Smartphone) for first time, I need to set the same wallpaper again then only i see the video. On other devices its working from first time itself.

    2. Set the video wallpaper on home screen and then set the another live wallpaper from available list. Its working fine. Now again set the video live wallpaper. Seen some scratched image which is not running sometimes running with similar kind of scratched images.

    3. In tablet, after changing orientation to landscape the Video changes the orientation but successfully with changed width and height. Now change the orientation to portrait again I seen the video with orientation changed but with half height and width full as per device width. Means the video is rendering from half of the screen.

    Can you please let me know on this?

    Please help me in this.

    Thanks,
    vishsoft

    • Unfortunately, this live wallpaper has a lot of bugs and probably needs a fresh rewrite. However, I haven’t had the time to update this. If I recall there’s an issue when you change the orientation. The app is supposed to re-load everything but for some reason the memory never gets released, resulting in video playing half-screen.

      If you want to work on this together, I’ll see if I can squeeze some time in :-)

      • Vishal says:

        Thanks for your reply.

        Yes I am interested to get this worked atleast orientation.

        I seen on code in onDestroy nothing is released from Renderer only called release method of renderer and release is empty.

        I will update you once I found something by adding logs on files to get the width, height and all required parameters.

        I think my 2 issue on above comment might be caused because of old memory images (memory never gets released).

        We will work.

        Thanks,
        vishsoft

  10. Pingback: How to play video as live wallpaper android? : Android Community - For Application Development

  11. mstudios says:

    I am looking for a programmer to do the same thing, code a video live wallpaper for android tablets. I could not find an email address on your blog, but please contact me if you are interested.

    • Tristan says:

      Hello,
      I have used this tutorial to deliver Video Live Wallpapers on Google Play.
      I can help you if you want: tristus1er [at] gmail [dot] com

  12. Chris says:

    Hi, Thanks for this tutorial. Since you specified Android 2.3 can’t play videos on wallpaper.
    Do you think, the latest versions of android support running videos on live wallpaper ?
    Pls let me know.
    Thanks

      • Chris says:

        Thanks for you reply. I am new to Android App Development. May be I am missing some point.
        I like to know, is there a direct API in later versions of android like 4.1, which supports running videos in live wallpaper. Instead of programming the functionality on our own using NDK.

  13. Hello,
    I struggled a lot with this project, but when I try to run I get the same message:
    libavcodec.so: File format not recognized

    What could be the cause of it?

    ___________________________________________________________
    $ /cygdrive/f/Kits/programare/Android/android-ndk-r5/ndk-build
    Install : libavcodec.so => libs/armeabi/libavcodec.so
    F:\Kits\programare\Android\android-ndk-r5\toolchains\arm-linux-androideabi-4.4.3
    \prebuilt\windows\bin\arm-linux-androideabi-strip.exe:D:/android/workspace/mapof
    prj/lwp/libs/armeabi/libavcodec.so: File format not recognized
    /cygdrive/f/Kits/programare/Android/android-ndk-r5/build/core/build-binary.mk:30
    5: recipe for target ‘/cygdrive/d/android/workspace/mapofprj/lwp/libs/armeabi/li
    bavcodec.so’ failed
    make: *** [/cygdrive/d/android/workspace/mapofprj/lwp/libs/armeabi/libavcodec.so
    ] Error 1

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s