Original article: http://www.cnblogs.com/scottwong/archive/2010/12/17/1909455.html
Recently I am working on an android project, and I am in a mess. I thought that Java was a first-class citizen on Android. After deep learning, I found that Java is a UI on Android. In addition, Java must be implemented in C language whatever you want. Android is a very bad operating system, and even Windows Mobile is inferior. Android can gain market share today only because Microsoft's Windows Phone 7 was still under development and iOS only used for iPhone, so mobile phone manufacturers have no choice, it can only be forced to use a Linux operating system that the Linux kernel development team does not recognize. The Linux kernel is the only advantage of Android. It is because of this that we can try to port the great open-source projects on Linux to Android to make up for the shortcomings of Android.
The multimedia features of Android are so weak and the limit is so large that I can only try to port FFMPEG to Android. Thanks to the sample code provided by havlenapetr and the instruction documents compiled by abitno. Without their contributions, I cannot port FFMPEG to Android. Next I will explain the detailed steps for porting FFMPEG to Android, hoping to help friends who are working on the same job.
1. Download necessary software
Oracle VM virtualbox 3.2.12
Ubuntu Desktop edition 10.10 32-bit
Android ndk r4b (access via wall)
Android ndk R5 (access via wall)
FFmpeg 0.6.1
Ii. Configure the compiling environment
- Create an Ubuntu Virtual Machine in virtualbox
- Run the sudo passwd root command on the Ubuntu Virtual Machine to start the root account.
- Log on to Ubuntu with the root account
- Extract the content from the android-ndk-r4b-linux-x86.zip to the/root directory
- Extract the content from the android-sdk_r07-linux_x86.tgz to the/root directory
- Extract the content from the ffmpeg-0.6.1.tar.bz2 to the/root/FFMPEG/JNI directory
3. Prepare to compile FFMPEG
- Write MK files
- Create an android. mk file in the/root/FFMPEG/JNI directory. The content is as follows:
include $(all-subdir-makefiles)
- Create an android. mk file in the/root/FFMPEG/JNI/ffmpeg-0.6.1 directory with the following content:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_WHOLE_STATIC_LIBRARIES := libavformat libavcodec libavutil libpostproc libswscale
LOCAL_MODULE := ffmpeg
include $(BUILD_SHARED_LIBRARY)
include $(call all-makefiles-under,$(LOCAL_PATH))
- Create an AV. mk file in the/root/FFMPEG/JNI/ffmpeg-0.6.1 directory with the following content:
# 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))
- Create an android. mk file in the/root/FFMPEG/JNI/ffmpeg-0.6.1/libavcodec directory with the following content:
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_LDLIBS := -lz
LOCAL_STATIC_LIBRARIES := $(FFLIBS)
LOCAL_MODULE := $(FFNAME)
include $(BUILD_STATIC_LIBRARY)
- Create an android. mk file in the/root/FFMPEG/JNI/ffmpeg-0.6.1/libavformat directory with the following content:
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)
- Create an android. mk file in the libavfilter, libavutil, libpostproc, and libswscale directories. The content is as follows:
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)
- Modify libm. h and makefile
- Edit the libm. h file in the/root/FFMPEG/JNI/ffmpeg-0.6.1/libavutil directory and delete the following static method
#if !HAVE_LRINT
static av_always_inline av_const long int lrint(double x)
{
return rint(x);
}
#endif /* HAVE_LRINT */
#if !HAVE_LRINTF
static av_always_inline av_const long int lrintf(float x)
{
return (int)(rint(x));
}
#endif /* HAVE_LRINTF */
#if !HAVE_ROUND
static av_always_inline av_const double round(double x)
{
return (x > 0) ? floor(x + 0.5) : ceil(x - 0.5);
}
#endif /* HAVE_ROUND */
#if !HAVE_ROUNDF
static av_always_inline av_const float roundf(float x)
{
return (x > 0) ? floor(x + 0.5) : ceil(x - 0.5);
}
#endif /* HAVE_ROUNDF */
#if !HAVE_TRUNCF
static av_always_inline av_const float truncf(float x)
{
return (x > 0) ? floor(x) : ceil(x);
}
#endif /* HAVE_TRUNCF */
- Edit the makefile files in the libavcodec, libavfilter, libavformat, libavutil, libpostproc, and libswscale directories, and delete
include $(SUBDIR)../subdir.mak
And
include $(SUBDIR)../config.mak
- Generate the config. h file
- Create a config. Sh file in the/root/FFMPEG/JNI/ffmpeg-0.6.1 directory and use Android ndk r4b to compile the file as follows:
PREBUILT=/root/android-ndk-r4b/build/prebuilt/linux-x86/arm-eabi-4.4.0
PLATFORM=/root/android-ndk-r4b/build/platforms/android-8/arch-arm
./configure --target-os=linux /
--arch=arm /
--enable-version3 /
--enable-gpl /
--enable-nonfree /
--disable-stripping /
--disable-ffmpeg /
--disable-ffplay /
--disable-ffserver /
--disable-ffprobe /
--disable-encoders /
--disable-muxers /
--disable-devices /
--disable-protocols /
--enable-protocol=file /
--enable-avfilter /
--disable-network /
--disable-mpegaudio-hp /
--disable-avdevice /
--enable-cross-compile /
--cc=$PREBUILT/bin/arm-eabi-gcc /
--cross-prefix=$PREBUILT/bin/arm-eabi- /
--nm=$PREBUILT/bin/arm-eabi-nm /
--extra-cflags="-fPIC -DANDROID" /
--disable-asm /
--enable-neon /
--enable-armv5te /
--extra-ldflags="-Wl,-T,$PREBUILT/arm-eabi/lib/ldscripts/armelf.x -Wl,-rpath-link=$PLATFORM/usr/lib -L$PLATFORM/usr/lib -nostdlib $PREBUILT/lib/gcc/arm-eabi/4.4.0/crtbegin.o $PREBUILT/lib/gcc/arm-eabi/4.4.0/crtend.o -lc -lm -ldl"
The content of Android ndk R5 compilation is as follows:
#!/bin/bash
PREBUILT=/root/android-ndk-r5/toolchains/arm-eabi-4.4.0/prebuilt/linux-x86
PLATFORM=/root/android-ndk-r5/platforms/android-8/arch-arm
./configure --target-os=linux /
--arch=arm /
--enable-version3 /
--enable-gpl /
--enable-nonfree /
--disable-stripping /
--disable-ffmpeg /
--disable-ffplay /
--disable-ffserver /
--disable-ffprobe /
--disable-encoders /
--disable-muxers /
--disable-devices /
--disable-protocols /
--enable-protocol=file /
--enable-avfilter /
--disable-network /
--disable-mpegaudio-hp /
--disable-avdevice /
--enable-cross-compile /
--cc=$PREBUILT/bin/arm-eabi-gcc /
--cross-prefix=$PREBUILT/bin/arm-eabi- /
--nm=$PREBUILT/bin/arm-eabi-nm /
--extra-cflags="-fPIC -DANDROID" /
--disable-asm /
--enable-neon /
--enable-armv5te /
--extra-ldflags="-Wl,-T,$PREBUILT/arm-eabi/lib/ldscripts/armelf.x -Wl,-rpath-link=$PLATFORM/usr/lib -L$PLATFORM/usr/lib -nostdlib $PREBUILT/lib/gcc/arm-eabi/4.4.0/crtbegin.o $PREBUILT/lib/gcc/arm-eabi/4.4.0/crtend.o -lc -lm -ldl"
- Open the terminal, enter the/root/FFMPEG/JNI/ffmpeg-0.6.1 directory, and run the following command
chmod +x config.sh
./config.sh
- Edit the config. h file in the/root/FFMPEG/JNI/ffmpeg-0.6.1 directory
#define restrict restrict
Change
#define restrict
4. start compiling FFMPEG
Many people compile FFMPEG using havlenapetr To Get A 1599-byte libffmpeg of 1.6kb size. so files, whether compiled with Android ndk r4b or compiled with Android ndk R5, are so annoying. I am also very depressed. I finally spent some time studying ndk and finally found a solution. The problem is still completely different between Android ndk r4b and Android ndk R5. Please continue to read it.
- Compile with Android ndk r4b
Open the setup. mk file in the android-ndk-r4b/build/toolchains/arm-eabi-4.4.0 directory and you will find Google defining a cmd-Build-shared-library function for compiling dynamic libraries. Google uses the private_whole_static_libraries function in the CMD-Build-shared-library function. But you cannot find the private_whole_static_libraries function in the android-ndk-r4b file in the build-binary.mk/build/Core directory ...... ? Why? Finally, I figured out that it was not my fault to get the correct libffmpeg. So file, but the android ndk r4b bug! Your sister! Your uncle! Ah, it is! Do not perform tests before release! A function is missing !!! (I dare say this is a bug because Google fixed this bug in Android ndk R5)
We had to manually fix this bug for Google. Fortunately, the modification method is very simple, just add a private_whole_static_libraries in the build-binary.mk file. For details, see
Build-binary.mk file before modification
Modified build-binary.mk File
After saving the build-binary.mk file, run the following command to compile
/root/android-ndk-r4b/ndk-build NDK_PROJECT_PATH=/root/ffmpeg
Then you will see that warning keeps appearing on the screen. After this shocking time, you will see that the libffmpeg. So file has been compiled and generated.
Check the libffmpeg. So file in the/root/FFMPEG/obj/local/armeabi directory. The file size is 12.2 MB.
Check the libffmpeg. So file in the/root/FFMPEG/libs/local/armeabi directory. The file size is 3.2 MB.
- Compile with Android ndk R5
Open the android-ndk-r5 file in the build-binary.mk/build/Core directory and find that Google did not forget private_whole_static_libraries this time, but the size of the libffmpeg. So file finally compiled is still incorrect. The problem this time is that the android-ndk-r5 is compiled by default using the arm-linux-androideabi-4.4.3 instead of the arm-eabi-4.4.0. But the CMD-Build-shared-library function defined in the setup. mk file in the android-ndk-r5/toolchains/arm-linux-androideabi-4.4.3 directory does not link static library files together to generate dynamic library files. So the solution is to add the ndk_toolchain parameter when running ndk-build, specifying the use of arm-eabi-4.4.0 for compilation. The complete command is as follows:
/root/android-ndk-r5/ndk-build NDK_PROJECT_PATH=/root/ffmpeg NDK_TOOLCHAIN=arm-eabi-4.4.0 NDK_PLATFORM=android-8
V. Conclusion
For details about how to compile an FFMPEG player running on Android, see havlenapetr/FFMPEG, tewilove/faplayer, nicoro, Android/FFMPEG dynamic module, and JNI simple wrapper (which requires access through the wall)
I hope this article will help you read this article.