Android - Mac & FFmpeg & AndroidStudio & CMake 环境搭建

2021-09-02 15:14:14 浏览数 (1)

基础环境

  • MacOS 10.12.3
  • AndroidStudio 2.3
  • NDK 13.1.*
  • FFmpeg 3.2.*

下载 FFmpeg 源码

1

git clone https://git.ffmpeg.org/ffmpeg.git

切换到 3.2 分支

1

git checkout -b 3.2 remotes/origin/release/3.2

当然你也可以去去官网下载压缩包。

编译 FFmpeg for Android

修改 FFmpeg 的 configure

打开 configure 文件,找到:

1234

SLIBNAME_WITH_MAJOR='$(SLIBNAME).$(LIBMAJOR)'LIB_INSTALL_EXTRA_CMD='$$(RANLIB)"$(LIBDIR)/$(LIBNAME)"'SLIB_INSTALL_NAME='$(SLIBNAME_WITH_VERSION)'SLIB_INSTALL_LINKS='$(SLIBNAME_WITH_MAJOR)$(SLIBNAME)'

替换成:

代码语言:javascript复制
1234SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'LIB_INSTALL_EXTRA_CMD='$$(RANLIB)"$(LIBDIR)/$(LIBNAME)"'SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'SLIB_INSTALL_LINKS='$(SLIBNAME)'

编写 Android 编译脚本

123456789101112131415161718192021222324252627282930313233343536373839

#!/bin/bashNDK=/Users/gavin/Develop/android-sdk/ndk-bundleSYSROOT=$NDK/platforms/android-15/arch-arm/TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64CPU=armPREFIX=$(pwd)/android/$CPU ADDI_CFLAGS="-marm"function build_one{./configure --prefix=$PREFIX --enable-shared --disable-static --disable-doc --disable-ffmpeg --disable-ffplay --disable-ffprobe --disable-ffserver --disable-avdevice --disable-doc --disable-symver --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- --target-os=linux --arch=arm --enable-cross-compile --sysroot=$SYSROOT --extra-cflags="-Os -fpic $ADDI_CFLAGS" --extra-ldflags="$ADDI_LDFLAGS" $ADDITIONAL_CONFIGURE_FLAGmake cleanmakemake install}build_one

前三行自行更换成自己的 NDK 路径即可,PREFIX 就是最终编译输出地址,根据情况也可以修改。

保存文件到 FFmpeg 根目录为 build_android.shchmod x build_android.sh 赋予执行权限。

编译

执行脚本进行编译。

1

./build_android.sh

小憩一会儿,编译完成。 进入 PREFIX 目录:

123456789101112131415

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

我们需要的 so 和头文件都有啦。

导入 Android 工程

对于如何开始一个 C 项目,官方已经有中文文档了:

https://developer.android.google.cn/studio/projects/add-native-code.html

官网有的东西不赘述,再次声明学什么东西优先看 官方文档,官方文档,官方文档,并且Google dev现在已经有很多中文资源了。

新建一个 C/C 工程

勾选 Include C Support 即可得到一个基于CMake的模板工程。

拷贝 so 和 incude 文件到 libs

因为我们只编译了 arm 版本的 so,所以需要把 so 拷到 armeabi-v7a 目录下,完整路径如下:

1234567891011121314151617181920212223

├── build.gradle├── libs│ ├── armeabi-v7a│ │ ├── libavcodec-57.so│ │ ├── libavfilter-6.so│ │ ├── libavformat-57.so│ │ ├── libavutil-55.so│ │ ├── libswresample-2.so│ │ └── libswscale-4.so│ └── include│ ├── libavcodec│ ├── libavfilter│ ├── libavformat│ ├── libavutil│ ├── libswresample│ └── libswscale├── proguard-rules.pro└── src└── main├── AndroidManifest.xml├── cpp├── java└── res

指定 jniLibs 路径

12345678

android {...sourceSets {main {jniLibs.srcDirs = ['libs']}}}

指定 abiFilters

因为 so 只有 armeabi-v7a 的,所以我们还需要指定一下 abi 为 armeabi-v7a

123456789

android {...defaultConfig {...ndk {abiFilters 'armeabi-v7a'}}}

编写 CMakeLists

脚本怎么写,有什么讲究其实官方文档已经很清楚了:创建 CMake 构建脚本

https://developer.android.google.cn/studio/projects/add-native-code.html#create-cmake-script

Java 引入 so 库

12345678910

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

运行测试

如果成功运行不报错的话,就证明一切没有问题。

编写 FFmpeg 测试代码

UI

C

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115

#include <jni.h>#include <string>extern "C" {#include <libavcodec/avcodec.h>#include <libavformat/avformat.h>#include <libavfilter/avfilter.h>JNIEXPORT jstring JNICALLJava_cn_gavinliu_android_ffmpeg_MainActivity_stringFromJNI(JNIEnv *env,jobject /* this */) {std::string hello = "Hello from C ";return env->NewStringUTF(hello.c_str());}JNIEXPORT jstring JNICALLJava_cn_gavinliu_android_ffmpeg_MainActivity_avformatinfo(JNIEnv *env,jobject /* this */) {char info[40000] = {0};av_register_all();AVInputFormat *if_temp = av_iformat_next(NULL);AVOutputFormat *of_temp = av_oformat_next(NULL);while (if_temp != NULL) {sprintf(info, "%sInput: %sn", info, if_temp->name);if_temp = if_temp->next;}while (of_temp != NULL) {sprintf(info, "%sOutput: %sn", info, of_temp->name);of_temp = of_temp->next;}return env->NewStringUTF(info);}JNIEXPORT jstring JNICALLJava_cn_gavinliu_android_ffmpeg_MainActivity_urlprotocolinfo(JNIEnv *env,jobject /* this */) {char info[40000] = {0};av_register_all();struct URLProtocol *pup = NULL;struct URLProtocol **p_temp = &pup;avio_enum_protocols((void **) p_temp, 0);while ((*p_temp) != NULL) {sprintf(info, "%sInput: %sn", info, avio_enum_protocols((void **) p_temp, 0));}pup = NULL;avio_enum_protocols((void **) p_temp, 1);while ((*p_temp) != NULL) {sprintf(info, "%sInput: %sn", info, avio_enum_protocols((void **) p_temp, 1));}return env->NewStringUTF(info);}JNIEXPORT jstring JNICALLJava_cn_gavinliu_android_ffmpeg_MainActivity_avcodecinfo(JNIEnv *env,jobject /* this */) {char info[40000] = {0};av_register_all();AVCodec *c_temp = av_codec_next(NULL);while (c_temp != NULL) {if (c_temp->decode != NULL) {sprintf(info, "%sdecode:", info);} else {sprintf(info, "%sencode:", info);}switch (c_temp->type) {case AVMEDIA_TYPE_VIDEO:sprintf(info, "%s(video):", info);break;case AVMEDIA_TYPE_AUDIO:sprintf(info, "%s(audio):", info);break;default:sprintf(info, "%s(other):", info);break;}sprintf(info, "%s[s]n", info, c_temp->name);c_temp = c_temp->next;}return env->NewStringUTF(info);}JNIEXPORT jstring JNICALLJava_cn_gavinliu_android_ffmpeg_MainActivity_avfilterinfo(JNIEnv *env, jobject /* this */) {char info[40000] = {0};avfilter_register_all();AVFilter *f_temp = (AVFilter *) avfilter_next(NULL);while (f_temp != NULL) {sprintf(info, "%s%sn", info, f_temp->name);f_temp = f_temp->next;}return env->NewStringUTF(info);}}

运行

更多

最简单的基于FFmpeg的移动端例子:Android HelloWorld http://blog.csdn.net/leixiaohua1020/article/details/47008825 FFmpeg 教程 http://blog.csdn.net/column/details/ffmpeg-devel.html


0 人点赞