基于最新版本ffmpeg3.2.x的编译和集成

时间:2023-02-06 20:12:49

前面用了大概6篇和大家分享了关于JNI的一系列内容,相信大家看过后肯定对JNI有了大致的了解。其实JNI的主要内容基本都是API的一些使用操作。

最近在研究Android音视频的一些内容,今天就和大家分享一下如何编译ffmpeg并集成到Android Studio环境下使用。

提示

1. 编译ffmpeg基于window10环境

2. Android Studio版本为2.2+

3. ffmpeg版本为3.x

一、编译ffmpeg

ffmpeg在linux操作系统下编译要方便的多,在window下需要我们做一些额外的工作,我们使用MinGw工具来编译。

1.安装MinGw

  MinGw的exe文件和源码开源在SourceForge,点击即可下载

2. 安装完成后,下载msys-basemingw-32-gcc-ada两个库文件即可。这里我们主要是使用gcc来完成编译工作。

3. 将bin目录配置到系统Path环境变量:

   基于最新版本ffmpeg3.2.x的编译和集成

4. 因为ffmpeg编译出来的so文件后缀不能直接在Android环境下使用,所以需要我们找到ffmpeg文件夹下的configure文件并打开,搜索SLIBNAME_WITH_MAJOR定位到该行,将原来的:

    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)' 

替换为:

    SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'  
    LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'  
    SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'  
    SLIB_INSTALL_LINKS='$(SLIBNAME)'

也就是修改编译出来的so文件后缀为.so形式。

5. 在ffmpeg目录下创建一个build_android.sh文件,拷贝如下代码:

#!/bin/bash
export TMPDIR=C:/Users/Song/Desktop/ffmpeg-3.2.4/tmpdir
NDK=D:/Android/android_studio/sdk/ndk-bundle
SYSROOT=$NDK/platforms/android-23/arch-arm/
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64
CPU=arm
PREFIX=C:/Users/Song/Desktop/ffmpeg-3.2.4/install
ADDI_CFLAGS="-marm"
function build_one
{
./configure \
--prefix=$PREFIX \
--enable-shared \
--disable-static \
--disable-doc \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-ffserver \
--disable-doc \
--disable-symver \
--enable-small \
--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_FLAG
make clean
make
make install
}
build_one

read -p "Press any key to continue." var

上面需要我们注意的地方有以下几点:

(1)TMPDIR :该字段指向一个文件夹目录,该文件夹路径可任意指定。作用是在编译ffmpeg期间,会生成一些临时文件用于存放在该目录,编译完成后,临时文件会自动清除。

(2)NDK:即你本地电脑NDK目录

(3)SYSROOT:根据你目前的NDK中platforms文件夹下的版本来设置。

(4)PREFIX:ffmpeg编译完成的so文件存放路径,可随意指定。

其它保持不变即可。

6. 执行gcc命令编译

 打开MinGW目录下的msys文件夹,找到msys.bat,打开:

 

  基于最新版本ffmpeg3.2.x的编译和集成

cd切换到ffmpeg根目录,执行./build_android.sh开始编译,这时,你可以先去泡杯咖啡喝上一口等待它编译完成。经锅一段时间后,当ffmpeg编译完成,打开第5步中我们配置的PREFIX所指向的目录。可以发现多了两个文件夹:

  基于最新版本ffmpeg3.2.x的编译和集成

其中,include就是编译出来的头文件,lib中就是so文件了:

  基于最新版本ffmpeg3.2.x的编译和集成  


     基于最新版本ffmpeg3.2.x的编译和集成

此时,对于ffmpeg的编译工作就搞定啦~,接下来我们就要将编译出来的文件集成到Android Studio中进行校验是否正确,如何集成呢?继续来看~

二、ffmpeg集成到Android Studio

Android Studio 2.2以上版本采用了cmake来代替老版本的ndk-build方式。在NDK的开发上也越来越方便。我们也使用cmake的方式来编译ffmpeg。

1. 将编译好的头文件和so库添加到cpp目录下

  基于最新版本ffmpeg3.2.x的编译和集成

2. 在main目录下创建jniLibs目录存放so文件:

  基于最新版本ffmpeg3.2.x的编译和集成

2. 配置CMakeLists文件

#添加ffmpeg对应的头文件目录
include_directories(src/main/cpp/ffmpeg3/include)

#添加库文件,实际上就是引入so文件,IMPORT代表从第三方引入
add_library(avcodec-lib SHARED IMPORTED)
#这句话是ffmpeg对应的so文件,so文件是放到JNILibs这个文件夹中
set_target_properties(avcodec-lib PROPERTIES IMPORTED_LOCATION
${CMAKE_CURRENT_SOURCE_DIR}/src/main/jniLibs/armeabi/libavcodec-57.so)

add_library(avdevic-lib SHARED IMPORTED)
set_target_properties(avdevic-lib PROPERTIES IMPORTED_LOCATION
${CMAKE_CURRENT_SOURCE_DIR}/src/main/jniLibs/armeabi/libavdevice-57.so)

add_library(avfilter-lib SHARED IMPORTED)
set_target_properties(avfilter-lib PROPERTIES IMPORTED_LOCATION
${CMAKE_CURRENT_SOURCE_DIR}/src/main/jniLibs/armeabi/libavfilter-6.so)

add_library(avformat-lib SHARED IMPORTED)
set_target_properties(avformat-lib PROPERTIES IMPORTED_LOCATION
${CMAKE_CURRENT_SOURCE_DIR}/src/main/jniLibs/armeabi/libavformat-57.so)

add_library(avutil-lib SHARED IMPORTED)
set_target_properties(avutil-lib PROPERTIES IMPORTED_LOCATION
${CMAKE_CURRENT_SOURCE_DIR}/src/main/jniLibs/armeabi/libavutil-55.so)

add_library(swresample-lib SHARED IMPORTED)
set_target_properties(swresample-lib PROPERTIES IMPORTED_LOCATION
${CMAKE_CURRENT_SOURCE_DIR}/src/main/jniLibs/armeabi/libswresample-2.so)

add_library(swscale-lib SHARED IMPORTED)
set_target_properties(swscale-lib PROPERTIES IMPORTED_LOCATION
${CMAKE_CURRENT_SOURCE_DIR}/src/main/jniLibs/armeabi/libswscale-4.so)

# 指定库CMake链接到您的目标库。 您可以链接多个库,例如你在中定义的库构建脚本,预构建的第三方库或系统库.
target_link_libraries( # 指定目标库.
native-l

# native-lib加载ffmpeg
avcodec-lib
avdevic-lib
avfilter-lib
avformat-lib
avutil-lib
swresample-lib
swscale-lib

# 将目标库链接到日志库包括在NDK.
${log-lib} )
在CmakeList文件中:

(1)首先使用include_directories配置了ffmpeg的头文件路径。将ffmpeg的头文件包含进来。

(2)将JniLibs目录下的so文件引入。

(3)将目标库和引入的so文件链接。

经过以上几步,ffmpeg就集成到了我们的工程下。接下来就是测试啦~

1. 打开app.gradle,在defaultConfig下配置:

externalNativeBuild {
cmake {
cppFlags "-frtti -fexceptions"
arguments '-DANDROID_TOOLCHAIN=clang','-DANDROID_STL=gnustl_static'
}
}

ndk {
abiFilters 'armeabi' //arm64-v8a','x86', 'x86_64', 'armeabi-v7a'
}

2. 在cpp目录下创建cpp文件,首先包含头文件

extern "C"{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
}

3. 调用ffmpeg的API函数,例如:

  基于最新版本ffmpeg3.2.x的编译和集成

如果程序没有提示错误,证明ffmpeg已经成功的集成啦~

ok,以上就是关于ffmpeg的编译和使用内容,有问题的朋友可以给我留言哈~