Below blog will explain the steps to setup and configure ffmpeg using android ndk.
ffmpeg is an open-source platform for recording, converting, playing and streaming video and audio. It includes libavcodec, a popular video/audio codec.
ffmpeg is an open-source platform for recording, converting, playing and streaming video and audio. It includes libavcodec, a popular video/audio codec.
Several popular Android applications are built based on FFmpeg, including RockPlayer, MoboPlayer, acrMedia, vitalPlayer, V-Cut Express etc. If you’re developing multimedia applications that needs a video/audio codec, ffmpeg is a good choice.
This blog covers how to compile ffmpeg for Android, and next blog will cover how to use ffmpeg to build a simple application.
The steps below are done on Ubuntu , android NDK , and ffmpeg . It should work on any versions of Android NDK and ffmpeg, but it may require minor changes.
Step 1:
Download and Install NDK from the android official site and copy it to a specific location.
Below is the link for android NDK:
Step 2:
Now link the android NDK with your eclipse using steps mentioned in the below url.
Step 3:
Create a new project in eclipse and with name "ffmpegExample" in eclipse and create a new folder named jni.
Step 4:
Download ffmpeg source from the below URL and place it to a specific location in your system.
Step 5:
Unpack ffmpeg sources to you "jni" directory folder of your project.
Step 6:
Create a file named "build4android.sh" in your "jni" directory folder of your project.
Step 7:
Copy and paste below text:
#!/bin/bash # Author: Dmitry Dzakhov (based on Guo Mingyu's script) # Creating conf.sh in ffmpeg directory NDK=/home/dmitrydzz/android-ndk PLATFORM=$NDK/platforms/android-8/arch-arm PREBUILT=$NDK/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86 output="conf.sh" [ -f conf.sh ] && echo "Old $output has been removed." echo '#!/bin/bash' > $output echo "PREBUILT=$PREBUILT" >> $output echo "PLATFORM=$PLATFORM" >> $output echo './configure --target-os=linux \ --prefix=./android/armv7-a \ --enable-cross-compile \ --extra-libs="-lgcc" \ --arch=arm \ --cc=$PREBUILT/bin/arm-linux-androideabi-gcc \ --cross-prefix=$PREBUILT/bin/arm-linux-androideabi- \ --nm=$PREBUILT/bin/arm-linux-androideabi-nm \ --sysroot=$PLATFORM \ --extra-cflags=" -O3 -fpic -DANDROID -DHAVE_SYS_UIO_H=1 -Dipv6mr_interface=ipv6mr_ifindex -fasm -Wno-psabi -fno-short-enums -fno-strict-aliasing -finline-limit=300 -mfloat-abi=softfp -mfpu=neon -marm -march=armv7-a -mtune=cortex-a8 " \ --disable-shared \ --enable-static \ --extra-ldflags="-Wl,-rpath-link=$PLATFORM/usr/lib -L$PLATFORM/usr/lib -nostdlib -lc -lm -ldl -llog" \ --enable-parsers \ --enable-encoders \ --enable-decoders \ --enable-muxers \ --enable-demuxers \ --enable-swscale \ --enable-swscale-alpha \ --disable-ffplay \ --disable-ffprobe \ --enable-ffserver \ --enable-network \ --enable-indevs \ --disable-bsfs \ --enable-filters \ --enable-avfilter \ --enable-protocols \ --disable-asm \ --enable-neon' >> $output # start configure sudo chmod +x $output echo "configuring..." ./$output || (echo configure failed && exit 1) # modify the config.h echo "modifying the config.h..." sed -i "s/#define restrict restrict/#define restrict/g" config.h # remove static functions in libavutil/libm.h echo "removing static functions in libavutil/libm.h..." sed -i "/static/,/}/d" libavutil/libm.h # modify Makefiles echo "modifying Makefiles..." sed -i "/include \$(SUBDIR)..\/subdir.mak/d" libavcodec/Makefile sed -i "/include \$(SUBDIR)..\/config.mak/d" libavcodec/Makefile sed -i "/include \$(SUBDIR)..\/subdir.mak/d" libavfilter/Makefile sed -i "/include \$(SUBDIR)..\/config.mak/d" libavfilter/Makefile sed -i "/include \$(SUBDIR)..\/subdir.mak/d" libavformat/Makefile sed -i "/include \$(SUBDIR)..\/config.mak/d" libavformat/Makefile sed -i "/include \$(SUBDIR)..\/subdir.mak/d" libavutil/Makefile sed -i "/include \$(SUBDIR)..\/config.mak/d" libavutil/Makefile sed -i "/include \$(SUBDIR)..\/subdir.mak/d" libpostproc/Makefile sed -i "/include \$(SUBDIR)..\/config.mak/d" libpostproc/Makefile sed -i "/include \$(SUBDIR)..\/subdir.mak/d" libswscale/Makefile sed -i "/include \$(SUBDIR)..\/config.mak/d" libswscale/Makefile # generate av.mk in ffmpeg echo "generating av.mk in ffmpeg..." echo '# LOCAL_PATH is one of libavutil, libavcodec, libavformat, or libswscale #include $(LOCAL_PATH)/../config-$(TARGET_ARCH).mak include $(LOCAL_PATH)/../config.mak OBJS := OBJS-yes := MMX-OBJS-yes := include $(LOCAL_PATH)/Makefile # collect objects OBJS-$(HAVE_MMX) += $(MMX-OBJS-yes) OBJS += $(OBJS-yes) FFNAME := lib$(NAME) FFLIBS := $(foreach,NAME,$(FFLIBS),lib$(NAME)) FFCFLAGS = -DHAVE_AV_CONFIG_H -Wno-sign-compare -Wno-switch -Wno-pointer-sign FFCFLAGS += -DTARGET_CONFIG=\"config-$(TARGET_ARCH).h\" ALL_S_FILES := $(wildcard $(LOCAL_PATH)/$(TARGET_ARCH)/*.S) ALL_S_FILES := $(addprefix $(TARGET_ARCH)/, $(notdir $(ALL_S_FILES))) ifneq ($(ALL_S_FILES),) ALL_S_OBJS := $(patsubst %.S,%.o,$(ALL_S_FILES)) C_OBJS := $(filter-out $(ALL_S_OBJS),$(OBJS)) S_OBJS := $(filter $(ALL_S_OBJS),$(OBJS)) else C_OBJS := $(OBJS) S_OBJS := endif C_FILES := $(patsubst %.o,%.c,$(C_OBJS)) S_FILES := $(patsubst %.o,%.S,$(S_OBJS)) FFFILES := $(sort $(S_FILES)) $(sort $(C_FILES))' > av.mk echo 'include $(all-subdir-makefiles)' > ../Android.mk echo 'LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_STATIC_LIBRARIES := libavformat libavcodec libavutil libpostproc libswscale LOCAL_MODULE := ffmpeg include $(BUILD_SHARED_LIBRARY) include $(call all-makefiles-under,$(LOCAL_PATH))' > Android.mk echo 'LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) include $(LOCAL_PATH)/../av.mk LOCAL_SRC_FILES := $(FFFILES) LOCAL_C_INCLUDES := \ $(LOCAL_PATH) \ $(LOCAL_PATH)/.. LOCAL_CFLAGS += $(FFCFLAGS) LOCAL_CFLAGS += -include "string.h" -Dipv6mr_interface=ipv6mr_ifindex LOCAL_LDLIBS := -lz LOCAL_STATIC_LIBRARIES := $(FFLIBS) LOCAL_MODULE := $(FFNAME) include $(BUILD_STATIC_LIBRARY)' > libavformat/Android.mk echo 'LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) include $(LOCAL_PATH)/../av.mk LOCAL_SRC_FILES := $(FFFILES) LOCAL_C_INCLUDES := \ $(LOCAL_PATH) \ $(LOCAL_PATH)/.. LOCAL_CFLAGS += $(FFCFLAGS) LOCAL_CFLAGS += -std=c99 LOCAL_LDLIBS := -lz LOCAL_STATIC_LIBRARIES := $(FFLIBS) LOCAL_MODULE := $(FFNAME) include $(BUILD_STATIC_LIBRARY)' > libavcodec/Android.mk echo 'LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) include $(LOCAL_PATH)/../av.mk LOCAL_SRC_FILES := $(FFFILES) LOCAL_C_INCLUDES := \ $(LOCAL_PATH) \ $(LOCAL_PATH)/.. LOCAL_CFLAGS += $(FFCFLAGS) LOCAL_STATIC_LIBRARIES := $(FFLIBS) LOCAL_MODULE := $(FFNAME) include $(BUILD_STATIC_LIBRARY)' > libavfilter/Android.mk echo 'LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) include $(LOCAL_PATH)/../av.mk LOCAL_SRC_FILES := $(FFFILES) LOCAL_C_INCLUDES := \ $(LOCAL_PATH) \ $(LOCAL_PATH)/.. LOCAL_CFLAGS += $(FFCFLAGS) LOCAL_STATIC_LIBRARIES := $(FFLIBS) LOCAL_MODULE := $(FFNAME) include $(BUILD_STATIC_LIBRARY)' > libavutil/Android.mk echo 'LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) include $(LOCAL_PATH)/../av.mk LOCAL_SRC_FILES := $(FFFILES) LOCAL_C_INCLUDES := \ $(LOCAL_PATH) \ $(LOCAL_PATH)/.. LOCAL_CFLAGS += $(FFCFLAGS) LOCAL_STATIC_LIBRARIES := $(FFLIBS) LOCAL_MODULE := $(FFNAME) include $(BUILD_STATIC_LIBRARY)' > libpostproc/Android.mk echo 'LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) include $(LOCAL_PATH)/../av.mk LOCAL_SRC_FILES := $(FFFILES) LOCAL_C_INCLUDES := \ $(LOCAL_PATH) \ $(LOCAL_PATH)/.. LOCAL_CFLAGS += $(FFCFLAGS) LOCAL_STATIC_LIBRARIES := $(FFLIBS) LOCAL_MODULE := $(FFNAME) include $(BUILD_STATIC_LIBRARY)' > libswscale/Android.mk # start build! echo "start ndk-building..." cd ../.. $NDK/ndk-build # Change previous line to "$NDK/ndk-build V=1" if you'll get errors. This will give some more information.
Change NDK build location in this script.
Step 8:
Go to your project folder directory and run the "build4android.sh" script.
After some time of ffmpeg building you'll get ffmpeg shared library and some static libraries in "<my-workspace>/ffmpegExample/obj" directory.
Step 9:
Now create a file named "mylib.c" in your "jni" folder directory and copy the below code.
#include <jni.h> #include <android/log.h> #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #define LOG_TAG "mylib" #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) jint Java_ru_dzakhov_ffmpeg_test_MainActivity_logFileInfo(JNIEnv * env, jobject this, jstring filename) { av_register_all(); AVFormatContext *pFormatCtx; const jbyte *str; str = (*env)->GetStringUTFChars(env, filename, NULL); if(av_open_input_file(&pFormatCtx, str, NULL, 0, NULL)!=0) { LOGE("Can't open file '%s'\n", str); return 1; } else { LOGI("File was opened\n"); LOGI("File '%s', Codec %s", pFormatCtx->filename, pFormatCtx->iformat->name ); } return 0; }
Step 10:
Now create a file named "Android.mk" in the same location and copy the below code.
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_LDFLAGS := -Wl,-rpath-link=/home/dmitrydzz/android-ndk/platforms/android-14/arch-arm/usr/lib/ -rpath-link=/home/dmitrydzz/android-ndk/platforms/android-14/arch-arm/usr/lib/ LOCAL_MODULE := libavformat LOCAL_SRC_FILES := ../obj/local/armeabi/libavformat.a LOCAL_CFLAGS := -march=armv7-a -mfloat-abi=softfp -mfpu=neon #надо именно эти 3 параметра! Нашёл это в android-ndk/docs/STANDALONE-TOOLCHAIN.html LOCAL_LDLIBS := -lz -lm -llog -lc -L$(call host-path, $(LOCAL_PATH))/$(TARGET_ARCH_ABI) -landprof include $(PREBUILT_STATIC_LIBRARY) include $(CLEAR_VARS) LOCAL_LDFLAGS := -Wl,-rpath-link=/home/dmitrydzz/android-ndk/platforms/android-14/arch-arm/usr/lib/ -rpath-link=/home/dmitrydzz/android-ndk/platforms/android-14/arch-arm/usr/lib/ LOCAL_MODULE := libavcodec LOCAL_SRC_FILES := ../obj/local/armeabi/libavcodec.a LOCAL_CFLAGS := -march=armv7-a -mfloat-abi=softfp -mfpu=neon LOCAL_LDLIBS := -lz -lm -llog -lc -L$(call host-path, $(LOCAL_PATH))/$(TARGET_ARCH_ABI) -landprof include $(PREBUILT_STATIC_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := libpostproc LOCAL_SRC_FILES := ../obj/local/armeabi/libpostproc.a LOCAL_CFLAGS := -march=armv7-a -mfloat-abi=softfp -mfpu=neon include $(PREBUILT_STATIC_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := libswscale LOCAL_SRC_FILES := ../obj/local/armeabi/libswscale.a LOCAL_CFLAGS := -march=armv7-a -mfloat-abi=softfp -mfpu=neon include $(PREBUILT_STATIC_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := libavutil LOCAL_SRC_FILES := ../obj/local/armeabi/libavutil.a LOCAL_CFLAGS := -march=armv7-a -mfloat-abi=softfp -mfpu=neon include $(PREBUILT_STATIC_LIBRARY) include $(CLEAR_VARS) LOCAL_LDLIBS += -llog -lz LOCAL_STATIC_LIBRARIES := libavformat libavcodec libpostproc libswscale libavutil LOCAL_C_INCLUDES += $(LOCAL_PATH)/ffmpeg LOCAL_SRC_FILES := mylib.c LOCAL_CFLAGS := -march=armv7-a -mfloat-abi=softfp -mfpu=neon LOCAL_MODULE := mylib include $(BUILD_SHARED_LIBRARY) LOCAL_PATH := $(call my-dir) LOCAL_C_INCLUDES += $(LOCAL_PATH)/ffmpeg include $(all-subdir-makefiles)
Step 11:
Go to the folder directory of your project the build the code to generate .so files using command "~/android-ndk/ndk-build"
Step 12:
Create a new activity in your project and copy the below code:
Don's forget to correct the package name and media file name.
Run the application to see the result.
References:
1) http://dmitrydzz-hobby.blogspot.in/2012/04/how-to-build-ffmpeg-and-use-it-in.html
2) https://github.com/bbcallen/ijkplayer/tree/master/android/ijkmediademo
3) http://www.roman10.net/how-to-build-ffmpeg-for-android/
4) http://code.google.com/p/android-fplayer/source/checkout
5) http://www.roman10.net/how-to-port-ffmpeg-the-program-to-androidideas-and-thoughts/
6) https://github.com/hoary/JavaAV
Go to the folder directory of your project the build the code to generate .so files using command "~/android-ndk/ndk-build"
Step 12:
Create a new activity in your project and copy the below code:
package ru.dzakhov.ffmpeg.test; import android.app.Activity; import android.os.Bundle; public class MainActivity extends Activity { private static native int logFileInfo(String filename); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); logFileInfo("/sdcard/VIDEO0050.mp4"); } static { System.loadLibrary("mylib"); } }
Don's forget to correct the package name and media file name.
Run the application to see the result.
References:
1) http://dmitrydzz-hobby.blogspot.in/2012/04/how-to-build-ffmpeg-and-use-it-in.html
2) https://github.com/bbcallen/ijkplayer/tree/master/android/ijkmediademo
3) http://www.roman10.net/how-to-build-ffmpeg-for-android/
4) http://code.google.com/p/android-fplayer/source/checkout
5) http://www.roman10.net/how-to-port-ffmpeg-the-program-to-androidideas-and-thoughts/
6) https://github.com/hoary/JavaAV