很多做NDK开发的人(像我这样从底层转过来的 >_<!)对于Android app的开发不是很理解,而ffmpeg的NDK开发现在又离不开Andorid app。网上虽然教程虽多,但是很多过时或者与NDK开发需求的不契合,或者ffmpeg与Android Studio一直在更新,从而造成了很多困扰,故写此教程,希望用户可以直接从github上面拉下来就能编译使用,同时一步一步讲解编写过程,对其中的一些大坑进行规避。
Android Studio Version: 3.1.3
ffmpeg Version:4.0
Android Version:O8.1
一. 编译ffmpeg
1. 从https://www.ffmpeg.org/上面下载4.0版本的ffmpeg
2. 编译ffmpeg的环境为:
Ubuntu 16.04 LTS, 64位
ndk version:android-ndk-r14b (需要自己下载)
abi support: armeabi armeabi-v7a arm64-v8a
3. 编写编译脚本,对于不同arm结构的编译脚本不同,对于armeabi-v7a架构的编译脚本,内容如下:
(其中xxx为android-ndk-r14b 的路径)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69#!/bin/bash PLATFORM=/xxx/android-ndk-r14b/platforms/android-19/arch-arm/ TOOLCHAIN=/xxx/android-ndk-r14b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64 PREFIX=./android/armeabi-v7a function build_android { ./configure --prefix=$PREFIX --target-os=android --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- --arch=arm --sysroot=$PLATFORM --cc=$TOOLCHAIN/bin/arm-linux-androideabi-gcc --nm=$TOOLCHAIN/bin/arm-linux-androideabi-nm --disable-shared --disable-ffmpeg --disable-ffplay --disable-ffprobe --disable-doc --disable-symver --enable-small --enable-gpl --enable-asm --enable-jni --enable-mediacodec --enable-decoder=h264_mediacodec --enable-hwaccel=h264_mediacodec --enable-decoder=hevc_mediacodec --enable-decoder=mpeg4_mediacodec --enable-decoder=vp8_mediacodec --enable-decoder=vp9_mediacodec --enable-nonfree --enable-version3 --extra-cflags="-Os -fpic $ADDI_CFLAGS -I$PLATFORM/usr/include" --extra-ldflags="$ADDI_LDFLAGS" $ADDITIONAL_CONFIGURE_FLAG make clean make -j8 make install $TOOLCHAIN/bin/arm-linux-androideabi-ld -rpath-link=$PLATFORM/usr/lib -L$PLATFORM/usr/lib -L$PREFIX/lib -soname libffmpeg.so -shared -nostdlib -Bsymbolic --whole-archive --no-undefined -o $PREFIX/libffmpeg.so libavcodec/libavcodec.a libavfilter/libavfilter.a libswresample/libswresample.a libavformat/libavformat.a libavutil/libavutil.a libswscale/libswscale.a libavdevice/libavdevice.a libpostproc/libpostproc.a -lc -lm -lz -ldl -llog --dynamic-linker=/system/bin/linker $TOOLCHAIN/lib/gcc/arm-linux-androideabi/4.9.x/libgcc.a } # arm v7vfp CPU=arm OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=vfp -marm -march=$CPU " ADDI_CFLAGS="-marm" build_android
对于arm64-v8a架构的编译脚本如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68#/bin/bash PLATFORM=/xxx/android-ndk-r14b/platforms/android-21/arch-arm64/ TOOLCHAIN=/xxx/android-ndk-r14b/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64 PREFIX=./android/arm64-v8a function build_android { ./configure --prefix=$PREFIX --target-os=android --cross-prefix=$TOOLCHAIN/bin/aarch64-linux-android- --arch=aarch64 --sysroot=$PLATFORM --cc=$TOOLCHAIN/bin/aarch64-linux-android-gcc --nm=$TOOLCHAIN/bin/aarch64-linux-android-nm --disable-shared --enable-static --disable-ffmpeg --disable-ffplay --disable-ffprobe --disable-doc --disable-symver --enable-small --enable-gpl --enable-asm --enable-jni --enable-mediacodec --enable-decoder=h264_mediacodec --enable-hwaccel=h264_mediacodec --enable-decoder=hevc_mediacodec --enable-decoder=mpeg4_mediacodec --enable-decoder=vp8_mediacodec --enable-decoder=vp9_mediacodec --enable-nonfree --enable-version3 --extra-cflags="-Os -fpic $ADDI_CFLAGS -I$PLATFORM/usr/include" --extra-ldflags="$ADDI_LDFLAGS" $ADDITIONAL_CONFIGURE_FLAG make clean make -j8 make install $TOOLCHAIN/bin/aarch64-linux-android-ld -rpath-link=$PLATFORM/usr/lib -L$PLATFORM/usr/lib -L$PREFIX/lib -soname libffmpeg.so -shared -nostdlib -Bsymbolic --whole-archive --no-undefined -o $PREFIX/libffmpeg.so libavcodec/libavcodec.a libavfilter/libavfilter.a libswresample/libswresample.a libavformat/libavformat.a libavutil/libavutil.a libswscale/libswscale.a libavdevice/libavdevice.a libpostproc/libpostproc.a -lc -lm -lz -ldl -llog --dynamic-linker=/system/bin/linker $TOOLCHAIN/lib/gcc/aarch64-linux-android/4.9.x/libgcc.a } # arm64-v8a CPU=arm64-v8a OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=vfp -march=$CPU " build_android
需要注意的是,这两个不同架构的编译脚本中,我都添加了h264_mediacodec硬件解码,这是以后需要讲解的一项内容。
而我这个版本也不是最全的版本,根据自己的需求来编译对应的ffmpeg,还是需要自己学习如何配置编译的,后面也会继续讲ffmpeg configure,暂时可以直接复制我的编译脚本来编译。
同时,这个脚本编译出来的是一个libffmpeg.so库,而不是分开的库,还是为了方便操作。
4. 直接执行./build_android_armeabi-v7a.sh,稍等片刻,就会在ffmpeg/android/armeabi-v7a/目录下生成libffmpeg.so 和 include目录,就是我们所需的lib库和头文件。
二. 将ffmpeg集成到Android Studio中
1. 新建工程,增加C++支持:
然后一路Next,最后可以添加上这两个选项:
点击Finish即可。
2. 这时候也就可以编译执行,放到板子上面执行了,可以看到屏幕上面出现了Hello C++的字符。
其实我们也没做什么,Android Studio就帮我们实现了,实在是太强大了。
3. 切换成Project视图,在main处右键,新建一个jniLibs目录,把刚编译好的lib库和头文件复制到该目录下。需要挑选对应abi的include目录,把里面所有的文件复制过来。(比如,对于armeabi-v7a架构,就把ffmpeg/android/armeabi-v7a/include目录的所有文件复制过去。)
4. 修改build.gradle文件,添加如下内容:
1
2
3ndk { abiFilters 'armeabi-v7a', 'arm64-v8a' }
如图所示:
5. 修改CMakeLists.txt,把ffmpeg的lib库添加进去:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28#CMake版本信息 cmake_minimum_required(VERSION 3.4.1) #ffmpeg so文件路径 set(lib_src_DIR ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}) #配置加载native依赖 include_directories(${CMAKE_SOURCE_DIR}/src/main/jniLibs/include) #动态方式加载ffmepg的so文件 第三方库加载方式 add_library(ffmpeg SHARED IMPORTED) #引入libffmpeg.so文件 set_target_properties(ffmpeg PROPERTIES IMPORTED_LOCATION ${lib_src_DIR}/libffmpeg.so) #CPP文件夹下待编译的c文件 add_library(native-lib SHARED ${CMAKE_SOURCE_DIR}/src/main/cpp/native-lib.cpp) #C 日志 ndk官方库 find_library(log-lib log) #静态库与动态库进行链接 相当于gcc命令行参数 -l。 target_link_libraries(native-lib android ffmpeg ${log-lib})
6. 添加第一个测试代码:
在MainActivity中仿照stringFromJNI,添加一个native方法string2FromJNI,然后点击左侧的红色感叹号,点击Create function xxx 让AS自动生成C++的对应方法,如图所示:
然后就会在 native-lib.cpp文件中,生成如下的函数模板:
1
2
3
4
5
6
7
8
9
10extern "C" JNIEXPORT jstring JNICALL Java_com_example_nxf31081_ffmpeg_1demo_11_MainActivity_string2FromJNI(JNIEnv *env, jobject instance) { // TODO return env->NewStringUTF(returnValue); }
然后我们对其进行稍加修改,返回ffmpeg的编译信息,如下所示:
1
2
3
4
5
6
7
8
9
10
11JNIEXPORT jstring JNICALL Java_com_example_nxf31081_ffmpeg_1android_1demo_11_MainActivity_string2FromJNI(JNIEnv *env, jobject instance) { // TODO char info[10000] = {0}; sprintf(info, "%s n", avcodec_configuration()); return env->NewStringUTF(info); }
然后修改MainActivity.java,把string2FromJNI()函数添加进去,如下所示:
1tv.setText(string2FromJNI());
最后,直接编译执行,就可以在APP上看到ffmpeg的编译信息了:
项目下载地址为:https://github.com/ZER0000/ffmpeg_android_demo.git
三. 总结
本篇文章实际的内容不多,主要是详细讲解了操作步骤,为以后的讲解做一个比较详细的铺垫,更主要的目的是为自己做一个记录,谁都知道我写博客的目的就是为了自己,哈哈~
最后
以上就是风趣果汁最近收集整理的关于基于Android O8.1的ffmpeg NDK 开发 - 1 - Hello World!的全部内容,更多相关基于Android内容请搜索靠谱客的其他文章。
发表评论 取消回复