Compile FFMPEG with Android ndk in Ubuntu

Source: Internet
Author: User

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

  1. Create an Ubuntu Virtual Machine in virtualbox
  2. Run the sudo passwd root command on the Ubuntu Virtual Machine to start the root account.
  3. Log on to Ubuntu with the root account
  4. Extract the content from the android-ndk-r4b-linux-x86.zip to the/root directory
  5. Extract the content from the android-sdk_r07-linux_x86.tgz to the/root directory
  6. Extract the content from the ffmpeg-0.6.1.tar.bz2 to the/root/FFMPEG/JNI directory

3. Prepare to compile FFMPEG

  1. Write MK files
    1. Create an android. mk file in the/root/FFMPEG/JNI directory. The content is as follows:

      include $(all-subdir-makefiles)
    2. 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))
    3. 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))
    4. 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)
    5. 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)
    6. 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)
  2. Modify libm. h and makefile
    1. 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 */
    2. 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
  3. Generate the config. h file
    1. 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"
    2. Open the terminal, enter the/root/FFMPEG/JNI/ffmpeg-0.6.1 directory, and run the following command
      chmod +x config.sh
      ./config.sh

    3. 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.

  1. 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.

  2. 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.

 

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.