最详细版Mac下编译FFmpeg,并移植到AndroidStudio(亲测能用)

时间:2021-7-21 作者:qvyue

最近项目空闲,开始调研学习Android音视频技术,又开始小白踩坑之路。。。搜了一圈,如果从零开始的话,ffmpeg应该是基础,必须要掌握的,网上的编译集成资料挺多的,然而,对着操作了一波,发现能用的挺少。。。磕磕碰碰的最后还是成功编译了,下面分享下集成经验~

集成准备

  • Android NDK : [android-ndk-r17c](版本太高的编译报错)(https://developer.android.google.cn/ndk/downloads/older_releases)
  • FFmpeg: FFmpge4.0.6

集成步骤

最详细版Mac下编译FFmpeg,并移植到AndroidStudio(亲测能用)
image.png
  • 修改FFmpeg目录下的configure文件(我用的Sublime Text)找到下面代码
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)'
  • 在解压后的FFmpeg包的根目录下新建一个.sh文件,这里我创建一个称为build_android.sh的文件,文件编辑内容如下:
ADDI_CFLAGS="-marm"
API=19
PLATFORM=arm-linux-androideabi
CPU=armv7-a
NDK=/Users/admin/android-ndk-r17c # 修改成自己本地的ndk路径。
SYSROOT=$NDK/platforms/android-$API/arch-arm/
ISYSROOT=$NDK/sysroot
ASM=$ISYSROOT/usr/include/$PLATFORM
TOOLCHAIN=$NDK/toolchains/$PLATFORM-4.9/prebuilt/darwin-x86_64
OUTPUT=/Users/admin/FFmpeg/android #自己指定一个输出目录,用来放生成的文件的。
function build
{
./configure 
--prefix=$OUTPUT 
--enable-shared 
--disable-static 
--disable-doc 
--disable-ffmpeg 
--disable-ffplay 
--disable-ffprobe 
--disable-avdevice 
--disable-doc 
--disable-symver 
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- 
--target-os=android 
--arch=arm 
--enable-cross-compile 
--sysroot=$SYSROOT 
--extra-cflags="-I$ASM -isysroot $ISYSROOT -Os -fpic -marm" 
--extra-ldflags="-marm" 
$ADDITIONAL_CONFIGURE_FLAG
  make clean
  make
  make install
}

build

这里主要修改的两个点我注释所在了,大家改成自己的目录就行了,第一个地方是你的NDK包下载后解压的路径,第二个地方是生成编译后的文件目录路径。

  • 编译build_android : 用终端cd 到当前目录 然后运行 sh build_android.sh(需要一段时间,会弹出多个授权框需要点同意),无报错即编译成功,如下图:

    最详细版Mac下编译FFmpeg,并移植到AndroidStudio(亲测能用)
    image.png
  • 编译后的文件如下图:

    最详细版Mac下编译FFmpeg,并移植到AndroidStudio(亲测能用)
    image.png
  • 新建Android项目,需要勾选支持C++:

    最详细版Mac下编译FFmpeg,并移植到AndroidStudio(亲测能用)
    image.png

    新建后的项目结构目录如下:

    最详细版Mac下编译FFmpeg,并移植到AndroidStudio(亲测能用)
    image.png
  • 注意:把CMakeLists.txt文件移动到跟src同级

    最详细版Mac下编译FFmpeg,并移植到AndroidStudio(亲测能用)
    image.png
  • 把我们的so文件和包括文件放到lib目录下,还有build.gradle文件和CMakeLists.txt文件的代码一并放出,如下:

    最详细版Mac下编译FFmpeg,并移植到AndroidStudio(亲测能用)
    image.png
  • 修改CMakeLists.txt

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

# 定义变量
set(distribution_DIR ../../../../libs)

# 添加库——自己编写的库
# 库名称:native-lib
# 库类型:SHARED,表示动态库,后缀为.so(如果是STATIC,则表示静态库,后缀为.a)
# 库源码文件:src/main/cpp/native-lib.cpp
add_library( native-lib
        SHARED
        src/main/cpp/native-lib.cpp )

# 添加库——外部引入的库
# 库名称:avcodec(不需要包含前缀lib)
# 库类型:SHARED,表示动态库,后缀为.so(如果是STATIC,则表示静态库,后缀为.a)
# IMPORTED表明是外部引入的库
add_library( avcodec
        SHARED
        IMPORTED)
# 设置目标属性
# 设置avcodec目标库的IMPORTED_LOCATION属性,用于说明引入库的位置
# 还可以设置其他属性,格式:PROPERTIES key value
set_target_properties( avcodec
        PROPERTIES IMPORTED_LOCATION
        ${distribution_DIR}/${ANDROID_ABI}/libavcodec.so)


find_library(
        log-lib
        log)
add_library( avfilter
        SHARED
        IMPORTED)
set_target_properties( avfilter
        PROPERTIES IMPORTED_LOCATION
        ${distribution_DIR}/${ANDROID_ABI}/libavfilter.so)

add_library( avformat
        SHARED
        IMPORTED)
set_target_properties( avformat
        PROPERTIES IMPORTED_LOCATION
        ${distribution_DIR}/${ANDROID_ABI}/libavformat.so)

add_library( avutil
        SHARED
        IMPORTED)
set_target_properties( avutil
        PROPERTIES IMPORTED_LOCATION
        ${distribution_DIR}/${ANDROID_ABI}/libavutil.so)

add_library( swresample
        SHARED
        IMPORTED)
set_target_properties( swresample
        PROPERTIES IMPORTED_LOCATION
        ${distribution_DIR}/${ANDROID_ABI}/libswresample.so)

add_library( swscale
        SHARED
        IMPORTED)
set_target_properties( swscale
        PROPERTIES IMPORTED_LOCATION
        ${distribution_DIR}/${ANDROID_ABI}/libswscale.so)

# 引入头文件
include_directories(libs/include)

# 告诉编译器生成native-lib库需要链接的库
# native-lib库需要依赖avcodec、avfilter等库
target_link_libraries( native-lib
        avcodec
        avfilter
        avformat
        avutil
        swresample
        swscale
        -landroid
        ${log-lib} )
  • 之后,修改build.gradle(:app)
apply plugin: 'com.android.application'

android {
    compileSdkVersion 30
    buildToolsVersion "30.0.2"

    defaultConfig {
        applicationId "com.sweet.sugarbeetest"
        minSdkVersion 21
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        externalNativeBuild {
            cmake {
                cmake {
                    cppFlags "-frtti -fexceptions -Wno-deprecated-declarations"
                }
                ndk {
                    abiFilters "armeabi-v7a"
                }
            }
        }

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

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
            version "3.10.2"
        }
    }
}

dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'

}
  • 最后,可以验证下是否成功,修改native-lib.cpp文件,打印FFmpeg版本号:
#include 
#include 

extern "C"{
#include >
}

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

最详细版Mac下编译FFmpeg,并移植到AndroidStudio(亲测能用)
image.png

步骤有点繁琐,希望小伙伴们能耐得住寂寞^^

声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:qvyue@qq.com 进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。