Android Studio上进行ffmpeg开发

闲来无事,学习下手机直播相关的知识。其中ffmpeg是必不可少的,下面简单介绍下如何在Android Studio上搭建一个可用的ffmpeg开发环境。


0.前置条件

首先你要准备以下环境:

Android Studio:我用的是2.3.3版本的,然后尝试编译一个非常一般的apk,并可以编译通过

其他的Android Build Tools:CMake、LLDB、NDK,这些都可以在SDK Manager里面下载到,如下图

Android Studio上进行ffmpeg开发_第1张图片

编译出的ffmpeg的so文件:如何编译ffmpeg网上教程很多,这里不再赘述了,我们需要编译出来的include、libavcodec-57.so、libavdevice-57.so、libavfilter-6.so、libavformat-57.so、libavutil-55.so、libswresample-2.so、libswscale-4.so


1.新建工程,勾选C++ Support,然后无脑下一步,完成(有一步会有两个复选框和一个下拉框,下拉框是编译工具、复选框一个是C++异常处理,一个是运行时支持)

Android Studio上进行ffmpeg开发_第2张图片

新建出来的工程应该是可以直接运行的,其中已经包含了C++代码和Jni调用,大家可以先看一下。


2.添加ffmpeg到Android工程,在项目根目录中新建ffmpeg文件夹,将我们编译好的so文件按照如下文件结构复制进去 

Android Studio上进行ffmpeg开发_第3张图片


3.修改CMakeLists.txt,添加ffmpeg模块

# 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.

set(FFMPEG_HOME ${CMAKE_SOURCE_DIR}/../ffmpeg)

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 )

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

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 )

# Import ffmpeg part
add_library( avcodec
             SHARED
             IMPORTED )
set_target_properties( avcodec
                       PROPERTIES IMPORTED_LOCATION
                       ${FFMPEG_HOME}/libs/${ANDROID_ABI}/libavcodec-57.so )

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

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

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

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

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

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

include_directories(${FFMPEG_HOME}/include/)

# 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
                       avdevice
                       avfilter
                       avformat
                       avutil
                       swresample
                       swscale

                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib} )

4.添加测试代码( 接下来会解决我遇到的一些问题

在MainActivity中添加一个native方法string2FromJNI,然后点击左侧红色感叹号,让IDE自动生成C++对应方法,生成后会是多出这部分代码

JNIEXPORT jstring JNICALL
Java_coding_yu_helloffmpeg_MainActivity_string2FromJNI(JNIEnv *env, jobject instance) {

    return env->NewStringUTF(result);
}


然后我们稍加修改,返回ffmpeg的编译信息,改成如下样子

#include "libavcodec/avcodec.h"

extern "C"
JNIEXPORT jstring JNICALL
Java_coding_yu_helloffmpeg_MainActivity_string2FromJNI(JNIEnv *env, jobject instance) {

    char info[10000] = {0};
    sprintf(info, "%s\n", avcodec_configuration());

    return env->NewStringUTF(info);
}

在loadLibrary中添加avcodec-57,然后让textview显示这个方法返回内容,然后点击运行按钮。。。然后遇到一堆问题。。。这些问题都是依次出现的,我就一起说了吧。

问题1:提示不能解决mips的依赖

解决方法:在gradle的defaultConfig中添加ndk平台指定

ndk {
    abiFilters "armeabi"
}

原因分析:因为当时编译的时候只编译了arm的ffmpeg二进制库,因此咱们只创建了armeabi文件夹,详情在第二步。编译器为什么会去找其他平台的呢?因为在CMakeLists.txt文件中有个变量是这样写的 /libs/${ANDROID_ABI}/libswscale-4.so,详情见第三步。因此我们只要指定apk的abi平台即可。


问题2:loadLibrary失败,Link不到 avcodec-57.so

解决方法:在app/src/main下新建jniLibs,将armeabi复制进去

原因分析:不是工程下已经导入了ffmpeg的so和include了么?为什么找不到?咱们在第二步导入的是编译用的,apk打包并不会打进去,Studio默认会把jniLibs的so打入apk,加上可以了(和集成第三方API的so一致)


问题3:avcodec_configuration方法未定义、string2FromJNI方法未实现

解决方法:添加extern “C”标识,修改后效果如下

#include 
#include 

extern "C" {
#include "libavcodec/avcodec.h"
}

extern "C"
JNIEXPORT jstring JNICALL
Java_coding_yu_helloffmpeg_MainActivity_string2FromJNI(JNIEnv *env, jobject instance) {

    char info[10000] = {0};
    sprintf(info, "%s\n", avcodec_configuration());

    return env->NewStringUTF(info);
}

extern "C"
JNIEXPORT jstring JNICALL
Java_coding_yu_helloffmpeg_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

然后应该没啥问题了吧。。。

这是项目地址:https://github.com/yuruxuan/HelloFFMpeg




你可能感兴趣的:(Android,ffmpeg)