Porting third-party libraries to Android

Source: Internet
Author: User

This article describes how to use Android ndk (r7) to set the android local code compilation tool chain and how to compile Android based on makefile. MK, and uses FFMPEG (0.8.5) as an example to describe how to use this tool chain port. The compiled library file can be used to call the FFMPEG decoding library through a local C/C ++ program, or the JNI interface can be compiled to call ffmepg using a Java program.

We all know that the general steps for software compilation are:

./configuremakemake install

You can also add parameters for customization, but the general process is as follows. To port an existing library to Android, there is a big difference. First, you need to build a cross-compilation environment to run the configure script to generate the configuration file, and then you need to write android. MK can be compiled.

Take FFMPEG as an example. running configure generates the files config. Mak, config. H, and libavutil/avconfig. H, which determine which modules are compiled by FFMPEG and whether to enable certain features. Of course, if you are familiar with it, you can manually modify these files, but the dependency is complex and error-prone. Then, you can manually compile the Android. mk file based on the original makefile. The following is a detailed process.

Note:: You cannot directly run the configure script on the host system because the environment is different from the target system (Android). This requires a cross-compilation environment.

1. Set the compilation tool chain

This step does not actually work, just to illustrate the next step. There are two equivalent methods, manually specifying a toolchain or using ndk to automatically generate a toolchain, detailed documentation for docs/STANDALONE-TOOLCHAIN.html under the ndk directory.

Manually specify a toolchain

It is to manually specify the location of the cross-compilation tool chain, where $ ndk is the directory where ndk is located. This method is a troublesome method. The following is to manually specify GCC and compile Foo. C:

Sysroot = $ ndk/platforms/Android-8/arch-arm # You can change the API version, 8 corresponds to Android 2.2 export cc = "$ ndk/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin/ARM-Linux-androideabi-GCC -- sysroot = $ sysroot" $ CC-O Foo. o-C Foo. c
2. Set compilation Parameters

There are many options when running the configure script. You can customize the options based on your needs and the target system. Run./configure -- help to understand all the options. Important information:

  • Required modules and functions: FFMPEG has many components and can be reduced as needed. For example, there are many codec instances. If you only need a few of them, you can block them and reduce the size of the Code. -> View the help in the FFMPEG/doc directory to understand the role of each module.
  • Enable certain Instruction Sets Based on the target CPU: Understand the target CPU architecture, typically arm11 or Cortex-A8, and whether the extension commands such as VFP and neon are supported. -> View the chip information provided by the CPU supplier.
  • Specify the cross-compilation tool chain: Set the location of the cross-compilation tool and set some necessary cflags and ldflags. -> View the GNU make help to understand the required options. Learn about Android ndk and its supported instruction sets and libraries.

My current target CPU is Qualcomm's 8255, architecture is Cortex-A8 support vfpv3 and neon Instruction Set; Target system is Android 2.3. You do not need to compile a library that supports file parsing and decoding. The following configurations meet my needs (manually specify a toolchain ):

Ndk = Your ndk directory sysroot = $ ndk/platforms/Android-9/arch-armprebuilt = $ ndk/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86. /configure -- disable-FFMPEG -- disable-ffplay -- disable-ffserver \ # block components irrelevant to decoding, delete the comment at the end of the line -- disable-ffprobe -- disable-swscale -- disable-postproc \ -- disable-BSFs -- disable-filters \ -- disable-avdevice -- disable-Network -- disable- devices \ -- disable-encoders -- disable-muxers \ # block encoding components -- disable-protocols -- enable-Protocol = file \ # only retain the local file protocol -- enable-Cross-compile -- target-OS = Linux \ -- arch = arm -- CPU = armv7-a \ -- enable-shared \ # Add -- sysroot = $ sysroot \ -- cc = $ prebuilt/bin directly when compiling with make /ARM-Linux-androideabi-GCC \ -- enable-memalign-hack \ -- extra-cflags = "-March = armv7-a-mfloat-Abi = softfp-mfpu = neon" # CPU features

If the running is successful, a detailed report is displayed, indicating that the features and options are enabled. Check these options to see if they are consistent with your own settings. Check config. h or config. Mak to check the values of all options. Check config. log to see why some options fail. CPU features have a major impact on performance. Because many algorithms use assembly language optimization, check the following config. Mak variables:

HAVE_ARMV5TE=yesHAVE_ARMV6=yesHAVE_ARMV6T2=yesHAVE_ARMVFP=yesHAVE_NEON=yesHAVE_VFPV3=yes 

Note:: In the configure script, a target platform feature is implemented by calling the compiler to compile some source code. For example, checking whether the compiler supports the neon instruction set is to check whether the Assembly instruction "vadd" can be compiled successfully. i16 q0, q0, q0 ".

Note:: If the CPU is the arm11 series (for example, Qualcomm msm7227), change the above configuration to "-- arch = arm -- CPU = armv6 \", and remove the -- extra-cflags section.

The acceleration effect of the neon instruction set is quite obvious, because many algorithms in FFMPEG use this optimization to make full use of the features of the neon single-instruction multi-data (SIMD. For example, in the 1.0 GHz Qualcomm msm8255, the playback level is insane's ape music, And the CPU usage drops from more than 80% to about 30%. In AVC decoding, the CPU usage also drops slightly.

3. Compile the library file

Note:: In fact, you can directly use the original makefile without writing Android. mk. If you set it to "-- enable-shared", you can directly make the compilation after running configure.If you want to use Android. mk, continue reading it. Otherwise, this article is complete..

Write Android. mk

Take the libavcodec module as an example. Let's open libavcodec/makefile and see the statements starting with objs. The excerpt is as follows:

# Parts needed for each different codecsobjs-$ (config_aandct) + = aandcttab. O # indicates that if config. in the Mak, config_aandct = yes is added to the variable objsobjs-$ (config_ac3dsp) + = ac3dsp. oobjs-$ (config_crystalhd) + = crystalhd. oobjs-$ (config_encoders) + = faandct. O jfdctfst. O jfdctint. oobjs-$ (config_dct) + = DCT. O dct32_fixed.o dct32_float.oobjs-$ (config_dwt) + = dwt. oobjs-$ (config_dxva2) + = dxva2.o

This is based on the config. Mak generated in the previous step to determine which files will be compiled. It is very important to add them to Android. mk. Create a new libavcodec/Android. mk file, copy the libavcodec/makefile statements related to objs, replace all *. O with *. C, that is, specify the source code file to be compiled.

# Libavcodec/android. mklocal_path: = $ (call my-DIR) include $ (clear_vars) include $ (local_path )/.. /config. makobjs = allcodecs. c \ audioconvert. c \ avpacket. c \ bitstream. c \ bitstream_filter.c \ dsputil. c \ faanidct. c \ fmtconvert. c \ imgconvert. c \ jrevdct. c \ options. c \ parser. c \ raw. c \ rawdec. c \ resample. c \ resample2.c \ simple_idct.c \ apedec. c \ utils. c \ # parts needed for your different codecsobjs-$ (config_aandct) + = aandcttab. cobjs-$ (config_ac3dsp) + = ac3dsp. cobjs-$ (config_crystalhd) + = crystalhd. cobjs-$ (config_encoders) + = faandct. c jfdctfst. c jfdctint. cobjs-$ (config_dct) + = DCT. c dct32_fixed.c dct32_float.cobjs-$ (config_dwt) + = dwt. cobjs-$ (config_dxva2) + = dxva2.c ### omitted include $ (local_path)/ARM/android. MK # Add an arm source file. The following describes local_cflags :=$ (cflags) # Add config. local_cppflags: = $ (cppflags) local_src_files = $ (sort $ (objs) $ (objs-Yes) # Add the required source file and use sort to prevent multiple local_module addition: = libavcodeclocal_module_tags: = optionallocal_prelink_module: = falselocal_shared_libraries + = libavutil libz # libavutil dependency. solocal_c_includes: = $ (local_path) \ # header file location $ (local_path)/Arm \ $ (local_path )/.. /\ external/zlib \ include $ (build_shared_library) # compile it into a dynamic library

In addition, libavcodec contains many Assembly optimization files. For example, if the target platform is arm, we need to add the source files under the libavcodec/ARM directory. It is also written based on libavcodec/ARM/makefile. The excerpt is as follows:

# Libavcodec/ARM/android. MK objs-$ (config_ac3dsp) + = ARM/ac3dsp_init_arm.c \ ARM/ac3dsp_arm.cobjs-$ (config_dca_decoder) + = ARM/inform \ # omitted in the middle, depending on the FFMPEG version, files may be different... Objs-$ (have_neon) + = ARM/kernel \ ARM/dsputil_neon.c \ ARM/fmtconvert_neon.c \ ARM/int_neon.c \ ARM/kernel \ $ (neon-objs-Yes)

Write Android. mk in each directory to be compiled. Finally, write an android. mk file that calls the subdirectory in the top-level directory of the compilation (next section ). Here we only compile three of the three required decoding modules, libavutil libavcodec libavformat. Libavutil depends on libz, libavcodec depends on libavutil, and libavformat depends on the first two.

Compile

You can use the ndk-build command to compile the file, but pay attention to the directory layout. If the current directory is $ project, you must set the FFMPEG source code directory and the top-level android. MK is placed in the $ Project/JNI directory, and ndk-build is run in the $ project directory.

# $ Project/JNI/android. MK, same as the FFMPEG directory local_path: = $ (call my-DIR) include $ (clear_vars) include $ (local_path)/FFMPEG/config. maklocal_shared_libraries: = libzinclude $ (local_path)/FFMPEG/libavutil/android. MK \ $ (local_path)/FFMPEG/libavcodec/android. MK \ $ (local_path)/FFMPEG/libavformat/android. mk

In addition, you can use the compilation command Mmm provided by the android source code to compile. You need to put the top Android. mk in the ffmpeg directory and modify the file path. I am using this method. The compiled library can be decoded normally using a self-made player. It should be equivalent to ndk-build.

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