Android - FFmpeg & Mac & AndroidStudio & CMake 环境搭建
2018-01-03 15:44
399 查看
AndroidStudio 2.2 开始支持
MacOS 10.12.3
AndroidStudio 2.3
NDK 13.1.*
FFmpeg 3.2.*
切换到 3.2 分支
当然你也可以去去官网下载压缩包。
打开 configure 文件,找到:
替换成:
前三行自行更换成自己的 NDK 路径即可,
保存文件到
执行脚本进行编译。
小憩一会儿,编译完成。
进入 PREFIX 目录:
我们需要的 so 和头文件都有啦。
对于如何开始一个 C++ 项目,官方已经有中文文档了:
https://developer.android.google.cn/studio/projects/add-native-code.html
官网有的东西不赘述,再次声明学什么东西优先看 官方文档,官方文档,官方文档,并且Google dev现在已经有很多中文资源了。
勾选 Include C++ Support 即可得到一个基于CMake的模板工程。
因为我们只编译了 arm 版本的 so,所以需要把 so 拷到 armeabi-v7a 目录下,完整路径如下:
因为 so 只有 armeabi-v7a 的,所以我们还需要指定一下 abi 为 armeabi-v7a
脚本怎么写,有什么讲究其实官方文档已经很清楚了:
创建
CMake 构建脚本
如果成功运行不报错的话,就证明一切没有问题。
CMake编译,网上的文章清一色都是
ndk-build,记录一下我用CMake搭建环境的过程。
基础环境
MacOS 10.12.3AndroidStudio 2.3
NDK 13.1.*
FFmpeg 3.2.*
下载
FFmpeg 源码
1 | git clone https://git.ffmpeg.org/ffmpeg.git |
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)' |
1234 | SLIBNAME_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/$CPUADDI_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 |
PREFIX就是最终编译输出地址,根据情况也可以修改。
保存文件到
FFmpeg根目录为
build_android.sh,
chmod +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 |
导入
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-v7a123456789 | android { ... defaultConfig { ... ndk { abiFilters 'armeabi-v7a' } }} |
编写
CMakeLists
脚本怎么写,有什么讲究其实官方文档已经很清楚了:创建
CMake 构建脚本
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 | # For more information about using CMake with Android Studio, read the# documentation: https://d.android.com/studio/projects/add-native-code.html# Sets the minimum version of CMake required to build the native library.cmake_minimum_required(VERSION 3.4.1)# Creates and names a library, sets it as either STATIC# or SHARED, and provides the relative paths to its source code.# You can define multiple libraries, and CMake builds them for you.# Gradle automatically packages shared libraries with your APK.add_library( # Sets the name of the library. native-lib # Sets the library as a shared library. SHARED # Provides a relative path to your source file(s). src/main/cpp/native-lib.cpp )add_library( avcodec-57 SHARED IMPORTED )set_target_properties( avcodec-57 PROPERTIES IMPORTED_LOCATION ../../../../libs/armeabi-v7a/libavcodec-57.so )add_library( avfilter-6 SHARED IMPORTED )set_target_properties( avfilter-6 PROPERTIES IMPORTED_LOCATION ../../../../libs/armeabi-v7a/libavfilter-6.so )add_library( avformat-57 SHARED IMPORTED )set_target_properties( avformat-57 PROPERTIES IMPORTED_LOCATION ../../../../libs/armeabi-v7a/libavformat-57.so )add_library( avutil-55 SHARED IMPORTED )set_target_properties( avutil-55 PROPERTIES IMPORTED_LOCATION ../../../../libs/armeabi-v7a/libavutil-55.so )add_library( swresample-2 SHARED IMPORTED )set_target_properties( swresample-2 PROPERTIES IMPORTED_LOCATION ../../../../libs/armeabi-v7a/libswresample-2.so )add_library( swscale-4 SHARED IMPORTED )set_target_properties( swscale-4 PROPERTIES IMPORTED_LOCATION ../../../../libs/armeabi-v7a/libswscale-4.so )include_directories( libs/include )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 )# Specifies libraries CMake should link to your target library. You# can link multiple libraries, such as libraries you define in this# build script, prebuilt third-party libraries, or system libraries.target_link_libraries( # Specifies the target library. native-lib avcodec-57 avfilter-6 avformat-57 avutil-55 swresample-2 swscale-4 # Links the target library to the log library # included in the NDK. ${log-lib} ) |
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
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162 | <?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="cn.gavinliu.android.ffmpeg.MainActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:id="@+id/button" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="protocol" android:text="Protocol" android:textAllCaps="false" /> <Button android:id="@+id/button2" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="filter" android:text="Filter" android:textAllCaps="false" /> <Button android:id="@+id/button3" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="format" android:text="Format" android:textAllCaps="false" /> <Button android:id="@+id/button4" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="codec" android:text="Codec" android:textAllCaps="false" /> </LinearLayout> <ScrollView android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/sample_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:scrollbars="vertical" android:text="Hello World!" /> </ScrollView></LinearLayout> |
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364 | package cn.gavinliu.android.ffmpeg;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.TextView;public class MainActivity extends AppCompatActivity { // Used to load the 'native-lib' library on application startup. 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"); } private TextView tv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Example of a call to a native method tv = (TextView) findViewById(R.id.sample_text); tv.setText(stringFromJNI()); } public void protocol(View view) { tv.setText(urlprotocolinfo()); } public void filter(View view) { tv.setText(avformatinfo()); } public void format(View view) { tv.setText(avfilterinfo()); } public void codec(View view) { tv.setText(avcodecinfo()); } /** * A native method that is implemented by the 'native-lib' native library, * which is packaged with this application. */ public native String stringFromJNI(); public native String avformatinfo(); public native String urlprotocolinfo(); public native String avcodecinfo(); public native String avfilterinfo();} |
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: %s\n", info, if_temp->name); if_temp = if_temp->next; } while (of_temp != NULL) { sprintf(info, "%sOutput: %s\n", 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: %s\n", info, avio_enum_protocols((void **) p_temp, 0)); } pup = NULL; avio_enum_protocols((void **) p_temp, 1); while ((*p_temp) != NULL) { sprintf(info, "%sInput: %s\n", 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[%10s]\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%s\n", info, f_temp->name); f_temp = f_temp->next; } return env->NewStringUTF(info);}} |
运行
相关文章推荐
- Android - FFmpeg & Mac & AndroidStudio & CMake 环境
- 在Mac上搭建React Native开发环境(iOS && Android)
- mac book pro + android studio + mx3搭建安卓开发测试环境
- Mac下Android Studio NDK 环境搭建并运行
- Android studio开环境搭建(mac 版)
- Android Studio Cmake & OpenCV3.2环境
- mac android studio 环境的搭建
- mac_android_studio_环境搭建
- mac android-studio环境搭建
- mac配置Android 环境,完整过程,其中包括遇到的设置$JAVA_HOME问题,新建项目报 Errors running builder 'Android Resource Manager问题
- Ubuntu搭建Android-Studio环境
- jni 入门 android的C编程之旅 --->环境搭建&&helloworld
- mac下android环境搭建笔记(android studio)
- Android开发学习之路--MAC下Android Studio开发环境搭建