FFmpeg In Android - 移植

移植FFmpeg到Android:
编译脚本
其实编译脚本网上也挺多的了,不过一开始可能没那么容易成功,需要耐心,细心, 还需要一点运气,比如有时NDK的版本编译通过不了,换另外一个NDK版本又可以了.下面记录一下自己的编译过程:

Linux 环境(Ubuntu 18.04.1 ,x86_64)
NDK 版本(android-ndk-r13b)
FFmpeg 版本(ffmpeg-3.3.8): 官网下载链接:https://ffmpeg.org/download.html

下载ffmpeg解压后放到文件夹/ffmpeg3.3.8_build下.

  • 首先需要对源代码中的configure文件进行修改。由于编译出来的动态库文件名的版本号在.so之后(例如“libavcodec.so.5.100.1”),而android平台不能识别这样文件名,所以需要修改这种文件名。在configure文件中找到下面几行代码:
LIBNAME_WITH_MAJOR='$(SLIBNAME).$(LIBMAJOR)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB)"$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_VERSION)'
SLIB_INSTALL_LINKS='$(SLIBNAME_WITH_MAJOR)$(SLIBNAME)'

***************** 替换为下面内容 ***************

SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB)"$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'
SLIB_INSTALL_LINKS='$(SLIBNAME)'
  • 在文件夹ffmpeg3.3.8_build下新建个脚本build_ffmpeg.sh,脚本内容如下,NDK路径需修改为自己的本地路径:
#!/bin/bash

cd ffmpeg-3.3.8

export NDK=/home/king/Android/android-ndk-r13b
export PREBUILT=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
export PLATFORM=$NDK/platforms/android-9/arch-arm/
export PREFIX=../simplefflib

build_one(){
./configure --target-os=linux\
 --prefix=$PREFIX \
 --enable-cross-compile \
 --enable-runtime-cpudetect \
 --extra-libs="-lgcc" \
 --disable-asm \
 --arch=arm \
 --cpu=armv7-a \
 --cc=$PREBUILT/bin/arm-linux-androideabi-gcc \
 --cross-prefix=$PREBUILT/bin/arm-linux-androideabi- \
 --disable-stripping \
 --nm=$PREBUILT/bin/arm-linux-androideabi-nm \
 --sysroot=$PLATFORM \
 --enable-gpl \
 --enable-shared \
 --disable-static \
 --enable-small \
 --disable-debug \
 --enable-parsers \
 --disable-encoders  \
 --enable-decoders \
 --disable-muxers \
 --enable-demuxers \
 --enable-swscale  \
 --disable-ffplay \
 --disable-ffprobe \
 --disable-ffserver \
 --disable-ffmpeg \
 --disable-network \
 --enable-indevs \
 --disable-bsfs \
 --disable-filters \
 --disable-protocols  \
 --enable-protocol=file \
 --extra-cflags="-fPIC -DANDROID -D__thumb__ -mthumb -Wfatal-errors -Wno-deprecated -mfloat-abi=softfp -marm -march=armv7-a"

make clean
make 
make install

}

build_one

cd ..

.
├── build_ffmpeg.sh
├── ffmpeg-3.3.8
└── simplefflib

执行脚本,编译成功后,simplefflib目录下得到头文件和动态库:

└── simplefflib
├── include
│ ├── libavcodec
│ ├── libavdevice
│ ├── libavfilter
│ ├── libavformat
│ ├── libavutil
│ ├── libpostproc
│ ├── libswresample
│ └── libswscale
└── lib
├── libavcodec-57.so
├── libavcodec.so -> libavcodec-57.so
├── libavdevice-57.so
├── libavdevice.so -> libavdevice-57.so
├── libavfilter-6.so
├── libavfilter.so -> libavfilter-6.so
├── libavformat-57.so
├── libavformat.so -> libavformat-57.so
├── libavutil-55.so
├── libavutil.so -> libavutil-55.so
├── libpostproc-54.so
├── libpostproc.so -> libpostproc-54.so
├── libswresample-2.so
├── libswresample.so -> libswresample-2.so
├── libswscale-4.so
├── libswscale.so -> libswscale-4.so
└── pkgconfig

将include目录下的头文件和lib目录下后面有数字的so库拷贝到自己的Android项目使用.

新建一个Android Studio C++项目,并配置好CMakeLists.txt,然后将头文件和动态库拷贝进项目:

.
├── app
│ ├── app.iml
│ ├── build.gradle
│ ├── CMakeLists.txt
│ ├── proguard-rules.pro
│ └── src
│ ├── androidTest
│ │ └── java
│ │ └── com
│ │ └── example
│ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── cpp
│ │ │ ├── include
│ │ │ │ ├── libavcodec
│ │ │ │ ├── libavdevice
│ │ │ │ ├── libavfilter
│ │ │ │ ├── libavformat
│ │ │ │ ├── libavutil
│ │ │ │ ├── libpostproc
│ │ │ │ ├── libswresample
│ │ │ │ └── libswscale
│ │ │ └── ndk-lib.cpp
│ │ ├── java
│ │ │ └── com
│ │ │ └── example
│ │ ├── jniLibs
│ │ │ └── armeabi-v7a
│ │ │ ├── libavcodec-57.so
│ │ │ ├── libavdevice-57.so
│ │ │ ├── libavfilter-6.so
│ │ │ ├── libavformat-57.so
│ │ │ ├── libavutil-55.so
│ │ │ ├── libpostproc-54.so
│ │ │ ├── libswresample-2.so
│ │ │ └── libswscale-4.so
│ │ └── res
│ │ ├── drawable
│ │ │ └── ic_launcher_background.xml
│ │ ├── drawable-v24
│ │ │ └── ic_launcher_foreground.xml

CMakeLists.txt配置内容如下:

cmake_minimum_required(VERSION 3.4.1)

set(shared_libs ${CMAKE_SOURCE_DIR}/src/main/jniLibs)

include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/include)

add_library(libavcodec-57 SHARED IMPORTED)
set_target_properties(libavcodec-57 PROPERTIES
        IMPORTED_LOCATION ${shared_libs}/${ANDROID_ABI}/libavcodec-57.so)

add_library(libavdevice-57 SHARED IMPORTED)
set_target_properties(libavdevice-57 PROPERTIES
        IMPORTED_LOCATION ${shared_libs}/${ANDROID_ABI}/libavdevice-57.so)

add_library(libavfilter-6 SHARED IMPORTED)
set_target_properties(libavfilter-6 PROPERTIES
        IMPORTED_LOCATION ${shared_libs}/${ANDROID_ABI}/libavfilter-6.so)

add_library(libavformat-57 SHARED IMPORTED)
set_target_properties(libavformat-57 PROPERTIES
        IMPORTED_LOCATION ${shared_libs}/${ANDROID_ABI}/libavformat-57.so)

add_library(libavutil-55 SHARED IMPORTED)
set_target_properties(libavutil-55 PROPERTIES
        IMPORTED_LOCATION ${shared_libs}/${ANDROID_ABI}/libavutil-55.so)

add_library(libpostproc-54 SHARED IMPORTED)
set_target_properties(libpostproc-54 PROPERTIES
        IMPORTED_LOCATION ${shared_libs}/${ANDROID_ABI}/libpostproc-54.so)

add_library(libswresample-2 SHARED IMPORTED)
set_target_properties(libswresample-2 PROPERTIES
        IMPORTED_LOCATION ${shared_libs}/${ANDROID_ABI}/libswresample-2.so)

add_library(libswscale-4 SHARED IMPORTED)
set_target_properties(libswscale-4 PROPERTIES
        IMPORTED_LOCATION ${shared_libs}/${ANDROID_ABI}/libswscale-4.so)

add_library(
    native-lib
    SHARED
    src/main/cpp/ndk-lib.cpp)

find_library( # Sets the name of the path variable.
              log-lib

              # Specifies the name of the NDK library that
              # you want CMake to locate.
              log )

target_link_libraries(native-lib
                       libavcodec-57
                       libavdevice-57
                       libavfilter-6
                       libavformat-57
                       libavutil-55
                       libpostproc-54
                       libswresample-2
                       libswscale-4
                       # Links the target library to the log library
                       # included in the NDK.
                       log)

要注意的是动态库不能随便放,而要放在armeabi,armeabi-v7a这样的目录下.

Java类代码如下:

static {
        System.loadLibrary("avcodec-57");
        System.loadLibrary("avdevice-57");
        System.loadLibrary("avfilter-6");
        System.loadLibrary("avformat-57");
        System.loadLibrary("avutil-55");
        System.loadLibrary("postproc-54");
        System.loadLibrary("swresample-2");
        System.loadLibrary("swscale-4");
        System.loadLibrary("native-lib");
    }

    public native void stringFromJNI();

测试一下调用ffmpeg的函数是否成功:

#include <jni.h>
#include <string>
#include <android/log.h>

#define  ANDROID_LOG_TAG    "native"
#define  ANDROID_LOG_ERR    "native"

#define  LOGD(...)  __android_log_print(ANDROID_LOG_DEBUG,ANDROID_LOG_TAG,__VA_ARGS__)
#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,ANDROID_LOG_TAG,__VA_ARGS__)
#define  LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,ANDROID_LOG_ERR,__VA_ARGS__)

#ifdef __cplusplus
extern "C"
{
#endif

    #include <libavcodec/avcodec.h>
    #include <libavformat/avformat.h>
    #include <libavfilter/avfilter.h>

#ifdef __cplusplus
};
#endif

extern "C" JNIEXPORT void JNICALL
Java_com_example_king_cmakedemo_NativeUtil_stringFromJNI(
        JNIEnv* env,
        jobject /* this */) {

    unsigned version = avformat_version();
    const char* license = avformat_license();

    LOGD("ffmpeg version %u, license:%s", version, license);

    const char * hello = "Hello from C++";
    LOGD(hello);
}

日志输出如下,证明调用ffmpeg函数成功了:
2018-10-23 10:48:17.823 1442-1442/com.example.king.cmakedemo D/native: ffmpeg version 3753828, license:GPL version 2 or later

猜你喜欢

转载自blog.csdn.net/kingdam578/article/details/83276925