NDK21编译ffmpeg5.0.1

导读

对于想要学习音视频开发的android开发者来说,使用NDK对FFmpeg进行交叉编译是一道必须迈过去的坎,网上关于使用NDK对FFmpeg进行交叉编译的教程有很多,
但是不经修改能顺利编译通过的比较少。

其实参照网上的教程不能编译通过很多时候不是人家的教程写的有问题,很多时候更多的是因为环境的差异导致了编译出错,而对于一个入门者来说编译报错了自己却不知道怎么改。

如果对交叉编译不太了解的童鞋们可以参考我之前写的文章:音视频学习之NDK交叉编译基础

NDK编译FFmpeg

今天我们来使用NDK对FFmpeg进行交叉编译并集成到Android Studio中去。

笔者的开发环境是:

  • 电脑系统 Mac OS
  • NDK 21.1.6352462
  • FFmpeg源码5.0.1

1、编写编译脚本

首先我们需要下载好对应版本的NDK和FFmpeg源码,然后我们新建一个编译脚本文件build_ffmpeg_android.sh:

#清空上次的编译
make clean
#配置你的NDK路径
export NDK=/Users/flyer/Documents/Android/sdk/ndk/21.1.6352462
TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/darwin-x86_64

function build_android
{
./configure \
--prefix=$PREFIX \
--disable-postproc \
--disable-debug \
--disable-doc \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-symver \
--disable-doc \
--disable-avdevice \
--disable-static \
--enable-shared \
--enable-neon \
--enable-hwaccels \
--enable-jni \
--enable-mediacodec \
--enable-decoder=h264_mediacodec \
--enable-decoder=hevc_mediacodec \
--enable-decoder=mpeg4_mediacodec \
--enable-hwaccel=h264_mediacodec \
--cross-prefix=$CROSS_PREFIX \
--target-os=android \
--arch=$ARCH \
--cpu=$CPU \
--cc=$CC \
--cxx=$CXX \
--enable-cross-compile \
--sysroot=$SYSROOT \
--extra-cflags="-Os -fpic $OPTIMIZE_CFLAGS" \
--extra-ldflags="$ADDI_LDFLAGS"

make clean
make -j16
make install

echo "============================build android ffmpeg end=========================="

}

#arm64-v8a 参数配置
ARCH=arm64
CPU=armv8-a
API=21
CC=$TOOLCHAIN/bin/aarch64-linux-android$API-clang
CXX=$TOOLCHAIN/bin/aarch64-linux-android$API-clang++
SYSROOT=$NDK/toolchains/llvm/prebuilt/darwin-x86_64/sysroot
CROSS_PREFIX=$TOOLCHAIN/bin/aarch64-linux-android-
PREFIX=$(pwd)/android/$CPU
OPTIMIZE_CFLAGS="-march=$CPU"

# 函数调用
build_android

注意脚本文件中的注释,要把NDK的路径改为自己的NDK路径,尽可能使用与笔者相同版本的NDK,比如使用NDKr23的版本就可能编译不通过,貌似是因为NDKr23的改掉导致了toolchains下一些列工具找不到了。

2、赋予脚本运行权限

将脚本文件拷贝到下载好的FFmpeg源码目录之下,然后使用命令行chmod +x build_ffmpeg_android.sh赋予脚本可执行权限。

3、运行编译脚本

运行命令行./build_ffmpeg_android.sh即可进行编译,如果编译成功可以在FFmpeg的源码目录下的android文件夹内找到对于的动态库和FFmpeg相关的头文件。
因为上述脚本通过PREFIX=$(pwd)/android/$CPU配置了编译的输出路径。

注意上述的脚本只编译了arm64-v8a架构的动态库,童鞋们可以尝试下如何编译其他架构的动态库。

集成到Android Studio中

1、 新建Android Studio Native工程

交叉编译成功后,我们通过Android Studio新建一个Native工程,不同的AS版本文件路径可能不一样,比如笔者的项目路径是这样的:

2、拷贝动态库和头文件到工程

然后我们在工程的libs目录下新建一个arm64-v8a目录,然后将我们编译出来的动态库文件拷贝到新建的arm64-v8a目录中去;

然后我们在cpp目录下新建一个ffmpeg_include目录用于存放FFmpeg的头文件,创建好之后我们将交叉编译目录include下头文件拷贝到新建的ffmpeg_include中去。

3、修改CMakeLists.txt

下面修改以下CMakeLists.txt配置文件,主要是配置FFmpeg动态库的搜索路径和头文件的搜索路径:


cmake_minimum_required(VERSION 3.10.2)

# 引入FFmpeg的头文件
include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/ffmpeg_include)

# 动态链接库或静态链接库的搜索路径
link_directories(${CMAKE_SOURCE_DIR}/libs/${CMAKE_ANDROID_ARCH_ABI})

#找到包含所有的cpp文件
file(GLOB allCpp src/main/cpp/*.*)

add_library(
        # 生成的库的名字
        flyffmpeg-lib

        # 动态库
        SHARED

        # 源文件
        ${allCpp} )


target_link_libraries( #目标库
        flyffmpeg-lib

        # 把ffmpeg的动态库依赖进来
        avformat
        avcodec
        avutil
        avfilter
        swscale
        swresample

        # NDK中的log库
        log )

注意上面的文件修改了最终生成的动态库的名字flyffmpeg-lib,所以在使用的时候需要注意一下加载正确的动态库。

4、修改build.gradle

这一步的目的主要是为了将libs目录下so文件打包进APK,我们将app目录下build.gradle修改成:

plugins {
    id 'com.android.application'
}

android {
    compileSdk 32

    defaultConfig {
        applicationId "com.fly.ffmpeg.practice"
        minSdk 21
        targetSdk 32
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        externalNativeBuild {
            cmake {
                cppFlags '-std=c++11'
            }

            // abiFilters
            ndk {
                abiFilters "arm64-v8a"
            }
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    externalNativeBuild {
        cmake {
            // 指定CMakeLists.txt路径
            path file('CMakeLists.txt')
            version '3.10.2'
        }
    }
    buildFeatures {
        viewBinding true
    }

    sourceSets {
        main {
            //将依赖库打进apk,否则可能出现找不到库
            jniLibs.srcDirs = ['libs']
        }
    }
}

dependencies {

    implementation 'androidx.appcompat:appcompat:1.4.1'
    implementation 'com.google.android.material:material:1.5.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}

注意注释部分即可。

5、修改native-lib.cpp

最后我们修改以下native-lib.cpp,在这里返回FFmpeg的配置:

#include <jni.h>
#include <string>

extern "C"{
#include <libavcodec/avcodec.h>
}
extern "C" JNIEXPORT jstring JNICALL
Java_com_fly_ffmpeg_practice_MainActivity_stringFromJNI(
        JNIEnv* env,
        jobject /* this */) {
    // 返回ffmpeg配置信息
    return env->NewStringUTF(avcodec_configuration());
}

运行如果可以能看到正确的配置信息则说明集成成功。

推荐阅读

FFmpeg连载1-开发环境搭建
FFmpeg连载2-分离视频和音频
FFmpeg连载3-视频解码
FFmpeg连载4-音频解码
FFmpeg连载5-音视频编码
FFmpeg连载6-音频重采样
FFmpeg连载8-视频合并以及替换视频背景音乐实战
ffplay调试环境搭建
ffplay整体框架
ffplay数据读取线程
ffplay音视频解码线程
ffplay音视频同步

关注我,一起进步,人生不止coding!!!
微信扫码关注

编译FFmpeg 6.0时,需要使用NDK 21版本进行相关操作。 首先,我们需要安装NDK并配置环境变量。可以从官方网站(developer.android.com/ndk)下载NDK安装包,并按照指示进行安装。安装完成后,将NDK的路径添加到系统环境变量中。 然后,我们需要获取FFmpeg 6.0版本的源代码。可以从FFmpeg的官方网站(ffmpeg.org)下载最新版本的源代码压缩包,并解压到本地目录中。 接下来,打开终端或命令提示符,并进入FFmpeg源代码所在的目录。执行以下命令进行配置: ./configure --arch=arm --cpu=armv7-a --target-os=android --enable-cross-compile --cross-prefix=arm-linux-androideabi- --sysroot=/path/to/ndk/sysroot --extra-cflags='-isysroot /path/to/ndk/sysroot/arch-arm -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -mthumb' --extra-ldflags='-Wl,-rpath-link=/path/to/ndk/sysroot/usr/lib/arm-linux-androideabi/,-L/path/to/ndk/sysroot/usr/lib/arm-linux-androideabi/ -nostdlib' --prefix=/path/to/output/directory 请确保将上述命令中的"/path/to/ndk"替换为NDK的实际路径,"/path/to/output/directory"替换为输出目录的实际路径。 配置完成后,执行以下命令进行编译: make -j4 其中"-j4"表示使用4个线程进行编译,可以根据实际情况进行调整。 编译完成后,执行以下命令进行安装: make install 至此,FFmpeg 6.0的编译过程就完成了。编译后的二进制文件和相关库将安装到指定的输出目录中。 需要注意的是,在编译过程中可能会遇到一些依赖项缺失的情况,需要根据具体错误信息进行处理。另外,NDK版本和FFmpeg版本之间的兼容性也需要注意,有时需要向上或向下调整NDK版本以确保编译成功。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值