一、新建Native C++ 工程

首先,不同的工具版本在开发过程中会存在一定的问题,以下为本篇文章的工具版本:

版本确定后,我们在AndroidStudio中,新建Native C++工程,项目名为​​FFmpegWorld​​​,包名为​​com.demo.ffmpegworld​​​,新建成功后,直接运行工程,如在首页出现​​Hello from C++​​字样,表示NDK开发的准备工作完成。如遇到无法运行等问题,可自行百度解决,这里不再赘述。

题外话:随着AS不断的更新,对NDK的支持越来越友好,并且伴随着CMake的编译方法,旧有的android.mk方法已经显得过于繁琐(可以参考:​​Android NDK开发之HelloWorld​​)。

二、导入FFmpeg库



将项目由​​Android​​视图转换为​​Project​​视图。



在​​libs​​目录下新建​​armeabi​​文件夹,将FFmpeg的​​arm\lib​​路径下带版本号的​​.so​​文件拷贝过来。



在​​libs​​目录下新建​​include​​文件夹,将FFmpeg的​​arm\include​​路径下的所有文件夹拷贝过来。
最终的拷贝结果如图:
NDK开发FFmpeg之HelloWorld_android



打开​​app/build.gradle​​文件,在​​android→defaultConfig​​结点下,新增​​sourceSets​​结点,并修改​​externalNativeBuild​​结点,具体内容为:

defaultConfig {
//新增sourceSets 结点
sourceSets {
main {
jniLibs.srcDirs = ["libs"]
}
}
//修改externalNativeBuild 结点
externalNativeBuild {
cmake {
cppFlags ""
abiFilters "armeabi"
}
}
}



打开​​src/main/cpp/CMakeLists.txt​​文件,在第一个​​add_library​​结点后,增加FFmpeg的关联代码(建议直接复制,路径容易出错):

#------------------------FFmpeg----------------------------------
include_directories(../../../libs/include)
set(DIR ../../../../libs)
MESSAGE("打印")
MESSAGE("路径 " ${DIR})
MESSAGE("路径 " ${CMAKE_CURRENT_SOURCE_DIR})
add_library(avcodec-58
SHARED
IMPORTED)
set_target_properties(avcodec-58
PROPERTIES IMPORTED_LOCATION
${DIR}/armeabi/libavcodec-58.so)
add_library(avdevice-58
SHARED
IMPORTED)
set_target_properties(avdevice-58
PROPERTIES IMPORTED_LOCATION
${DIR}/armeabi/libavdevice-58.so)
add_library(avformat-58
SHARED
IMPORTED)
set_target_properties(avformat-58
PROPERTIES IMPORTED_LOCATION
${DIR}/armeabi/libavformat-58.so)
add_library(avutil-56
SHARED
IMPORTED)
set_target_properties(avutil-56
PROPERTIES IMPORTED_LOCATION
${DIR}/armeabi/libavutil-56.so)
add_library(swresample-3
SHARED
IMPORTED)
set_target_properties(swresample-3
PROPERTIES IMPORTED_LOCATION
${DIR}/armeabi/libswresample-3.so)
add_library(swscale-5
SHARED
IMPORTED)
set_target_properties(swscale-5
PROPERTIES IMPORTED_LOCATION
${DIR}/armeabi/libswscale-5.so)
add_library(avfilter-7
SHARED
IMPORTED)
set_target_properties(avfilter-7
PROPERTIES IMPORTED_LOCATION
${DIR}/armeabi/libavfilter-7.so)
#------------------------FFmpeg----------------------------------



三、编写Native代码


  1. 编写java类​​FFmpegUtil​​:
    ​package com.demo.ffmpegworld; public class FFmpegUtil { static { System.loadLibrary("ffmpeg-util"); } /** * 获取FFmpeg的配置信息 * * @return 配置信息字符串 */ public static native String getAvcodecConfiguration(); } ​
  2. 在​​app/src/main/cpp​​文件夹下,创建​​ffmpeg-util.h​​文件:
    ​#ifndef FFMPEG_NATIVE_LIB_H #define FFMPEG_NATIVE_LIB_H #include <jni.h> #include <string> #include <android/log.h> extern "C" { //编码 #include "libavcodec/avcodec.h" //封装格式处理 #include "libavformat/avformat.h" //像素处理 #include "libswscale/swscale.h" #include <android/native_window_jni.h> #include <unistd.h> JNIEXPORT jstring JNICALL Java_com_demo_ffmpegworld_FFmpegUtil_getAvcodecConfiguration(JNIEnv *env, jobject /* this */); } #define LOGI(FORMAT, ...) __android_log_print(ANDROID_LOG_INFO,"jason",FORMAT,##__VA_ARGS__); #define LOGE(FORMAT, ...) __android_log_print(ANDROID_LOG_ERROR,"jason",FORMAT,##__VA_ARGS__); #endif //FFMPEG_NATIVE_LIB_H ​
  3. 在​​app/src/main/cpp​​文件夹下,创建​​ffmpeg-util.cpp​​文件:
    ​#include "ffmpeg-util.h" extern "C" JNIEXPORT jstring JNICALL Java_com_demo_ffmpegworld_FFmpegUtil_getAvcodecConfiguration(JNIEnv *env, jobject /* this */) { std::string hello = "Hello from C++"; char info[10000] = {0}; sprintf(info, "%s\n", avcodec_configuration()); return env->NewStringUTF(info); } ​

四、修改CMakeLists文件,编译运行



打开​​src/main/cpp/CMakeLists.txt​​文件,修改第一个​​add_library​​和最后一个​​target_link_libraries​​结点,修改内容分别为:

#add_library结点 
add_library( # Sets the name of the library.
ffmpeg-util
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
ffmpeg-util.cpp)
#target_link_libraries结点
target_link_libraries( # Specifies the target library.
ffmpeg-util
# Links the target library to the log library
# included in the NDK.
avcodec-58
avdevice-58
avformat-58
avutil-56
swresample-3
swscale-5
-landroid # Add this.
${log-lib})



修改​​MainActivity​​代码,删除其自带的native方法,改为调用我们刚写好的​​getAvcodecConfiguration​​方法:

public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

// Example of a call to a native method
TextView tv = findViewById(R.id.sample_text);
tv.setText(FFmpegUtil.getAvcodecConfiguration());
}
}



编译运行,成功后可以看到生成的​​.so​​包可在​​app/build/intermediates/cmake/debug/obj​​文件夹下找到。安卓界面显示详细的配置信息,至此FFmpeg的HelloWorld程序完成。
NDK开发FFmpeg之HelloWorld_android_02