第一次完成FFmepg的移植,编译ffmpeg4Android

本文主要实现了FFmpeg的编译和移植,首先在linux下将官网下载的源码编译成.so文件,然后使用android-studio配合NDK工具,将.so文件移植到android项目当中,简单地介绍了如何一步步完成FFmpeg的编译流程

参考文章:手把手图文并茂教你用Android Studio编译FFmpeg库并移植

下面是我自己在ubuntu下编译

准备的编译工具

Git,NDK

安装git,检查本地git,git --version

直接用命令符安装: sudo apt install git

也可以去官网下载,git官网下载

如果已经有了git,想更新到最新版,可以输入 git clone https://github.com/git/git,再进行编译安装

然后下载NDK(现在已经有13的版本了),推荐使用android studio安装ndk,下载的ndk路径默认在AndroidSDK的ndk-boudle文件中

配置NDK的环境

使用terminal配置电脑的环境,(个人电脑,我直接以管理员权限配置的系统环境变量)

sudo gedit /etc/profile

打开之后,把我们的ndk路径配置进来,

	#Android NDK
	export ANDROID_NDK=/path/to/ndk(你的ndk解压路径)
	export PATH=$PATH:$ANDROID_NDK

下载ffmpeg的最新的源码

新建一个ffempeg的工作文件夹,例如 mkdir workplace

git clone https://git.ffmpeg.org/ffmpeg.git

也可以直接去官网下载:ffmpeg官网下载

修改ffmpeg的configure文件(跳过,新版本不需要修改,2022年)

为了保证我们编译出的文件是以.so的后缀名
将文本中的3209-3212这4行:

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目录执行如下命令:

./configure --help

当然此脚本中,我们只需要设置几个我们比较关心的配置。

1. NDK的路径:
    NDK=/path/to/ndk

2. 编译的ndk plaform版本:
    SYSROOT=$NDK/platforms/android-23/arch-arm/

3. 交叉编译工具:
    TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64

4. CPU平台:
    CPU=arm

5. 编译完成后安装目录(当前目录下的android文件夹):
    PREFIX=./android/$CPU

确定我们需要的配置之后,在ffmpeg的目录下面新建一个脚本 build4android.sh
老版本的ffmpeg:

	#!/bin/sh
	NDK=/path/to/ndk
	SYSROOT=$NDK/platforms/android-23/arch-arm/
	TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
	CPU=arm
	PREFIX=./android/$CPU
	ADDI_CFLAGS="-marm"
	config_para()
	{
	./configure \
		--prefix=$PREFIX \
		--enable-shared \
		--disable-static \
		--disable-doc \
		--disable-ffmpeg \
		--disable-ffplay \
		--disable-ffprobe \
		--disable-ffserver \
		--disable-avdevice \
		--disable-doc \
		--disable-symver \
		--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
	}
	config_para

2022年新版本的脚本:(由于gcc弃用,需要使用clang,AR/AS/CC/CXX/LD/NM/RANLIB/STRIP这几个编译器最好都配一下)

#!/bin/bash

# 当前系统
export HOST_TAG=linux-x86_64  # 如果你的mac,修改成darwin-x86_64
# 支持的 Android CUP 架构,目前推荐64位的
export ARCH=aarch64
export CPU=armv8-a
# 32位
#export ARCH=armv7a
#export CPU=armv7-a
# 支持的 Android 最低系统版本
export MIN=21
export ANDROID_NDK_PLATFORM=android-21
# 编译输出目录
export PREFIX=$(pwd)/android/$CPU
# NDK 根目录
export NDK=$ANDROID_NDK_HOME
export MIN_PLATFORM=$NDK/platforms/android-$MIN
export SYSROOT=$NDK/sysroot
export TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/$HOST_TAG
# **请注意,ARCH的值决定了AR/AS/CC/CXX/LD/NM/RANLIB/STRIP的值,ls $TOOLCHAIN 查看对应的具体编译器名字**
export AR=$TOOLCHAIN/bin/$ARCH-linux-android-ar
export AS=$TOOLCHAIN/bin/$ARCH-linux-android-as
export CC=$TOOLCHAIN/bin/$ARCH-linux-android$MIN-clang
export CXX=$TOOLCHAIN/bin/$ARCH-linux-android$MIN-clang++
export LD=$TOOLCHAIN/bin/$ARCH-linux-android-ld
export NM=$TOOLCHAIN/bin/$ARCH-linux-android-nm
export RANLIB=$TOOLCHAIN/bin/$ARCH-linux-android-ranlib
export STRIP=$TOOLCHAIN/bin/$ARCH-linux-android-strip

#添加额外的编译选项
EXTRA_CFLAGS="" 
EXTRA_LDFLAGS=""

config_para()
{
./configure \
--prefix=$PREFIX \
--ar=$AR \
--as=$AS \
--cc=$CC \
--cxx=$CXX \
--nm=$NM \
--ranlib=$RANLIB \
--strip=$STRIP \
--arch=$ARCH \
--target-os=android \
--enable-cross-compile \
--disable-asm \
--enable-shared \
--disable-static \
--disable-ffprobe \
--disable-ffplay \
--disable-ffmpeg \
--disable-debug \
--disable-symver \
--disable-stripping \
--extra-cflags="-Os -fpic $EXTRA_CFLAGS" \
--extra-ldflags="$EXTRA_LDFLAGS"

make clean
make
make install
}

config_para

开始编译

进入我们的FFmpeg的源码目录,执行刚才的脚本:
(先增加执行权限 sudo chmod +x build4android.sh,以防权限不够)

./build4anroid.sh
编译完成

生成的android/arm/目录中的文件,图中标出的为链接文件可以删除:
编译成功

移植我们的.so文件

拷贝.so文件到android-studio工程文件中

在android-studio中切换成project工程目录模式,在app/src/main目录下面新建一个jni文件夹,将上面第6步中的include文件夹拷贝到此文件夹中,再在jni文件夹中新建一个lib文件夹,将.so文件拷贝进来,新建Android.mk,Application.mk和c文件目录结构如下:

├── Android.mk
├── Application.mk
├── ffmpeg-jni.c
├── include
│   ├── libavcodec
│   ├── libavfilter
│   ├── libavformat
│   ├── libavutil
│   ├── libswresample
│   └── libswscale
└── lib
    ├── libavcodec.so
    ├── libavfilter.so
    ├── libavformat.so
    ├── libavutil.so
    ├── libswresample.so
    └── libswscale.so

编写Android.mk文件

    
    LOCAL_PATH := $(call my-dir)
    
    include $(CLEAR_VARS)
    LOCAL_MODULE:= libavcodec
    LOCAL_SRC_FILES:= lib/libavcodec.so
    LOCAL_EXPORT_C_INCLUDES:= $(LOCAL_PATH)/include
    include $(PREBUILT_SHARED_LIBRARY)
    
    include $(CLEAR_VARS)
    LOCAL_MODULE:= libavformat
    LOCAL_SRC_FILES:= lib/libavformat.so
    LOCAL_EXPORT_C_INCLUDES:= $(LOCAL_PATH)/include
    include $(PREBUILT_SHARED_LIBRARY)
    
    include $(CLEAR_VARS)
    LOCAL_MODULE:= libswscale
    LOCAL_SRC_FILES:= lib/libswscale.so
    LOCAL_EXPORT_C_INCLUDES:= $(LOCAL_PATH)/include
    include $(PREBUILT_SHARED_LIBRARY)
    
    include $(CLEAR_VARS)
    LOCAL_MODULE:= libavutil
    LOCAL_SRC_FILES:= lib/libavutil.so
    LOCAL_EXPORT_C_INCLUDES:= $(LOCAL_PATH)/include
    include $(PREBUILT_SHARED_LIBRARY)
    
    include $(CLEAR_VARS)
    LOCAL_MODULE:= libavfilter
    LOCAL_SRC_FILES:= lib/libavfilter.so
    LOCAL_EXPORT_C_INCLUDES:= $(LOCAL_PATH)/include
    include $(PREBUILT_SHARED_LIBRARY)
    
    include $(CLEAR_VARS)
    LOCAL_MODULE:= libswresample
    LOCAL_SRC_FILES:= lib/libswresample.so
    LOCAL_EXPORT_C_INCLUDES:= $(LOCAL_PATH)/include
    include $(PREBUILT_SHARED_LIBRARY)
    
    include $(CLEAR_VARS)
    LOCAL_MODULE:= FFmpegCodec
    LOCAL_SRC_FILES:= ffmpeg-jni.c
    LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
    LOCAL_LDLIBS := -llog  -lz
    LOCAL_SHARED_LIBRARIES := avcodec avfilter avformat avutil  swresample swscale
    include $(BUILD_SHARED_LIBRARY)

编写Application.mk文件

    APP_ABI :=armv8-a  //这里可选armeabi-v7a,x86,mips和all等
    APP_PLATFORM := android-21
    APP_OPTIM := release //默认是relaese,也可以设置成debug
    APP_STL := gnustl_static //这里是可选,当你编写下面的C文件的时候这里就可以体现出作用,例如你要使用`#include <string>`这个库的时候,默认的system库是没有包含这个的

编写C文件

在上面编写的Android.mk中,我们制定了c文件的名字为ffmpeg-jni.c,所以c文件的与此保持一致,

函数申明语法:JNIEXPORT jstring Java_包名_activity名_函数名,包名中间的点号.全部变成下划线_

例如:我在包名com.righere.ffmpegndkbuild下面的MainActivity中要使用avcodecInfo这个函数,

JNIEXPORT jstring Java_com_righere_ffmpegndkbuild_MainActivity_avcodecInfo

#include <stdio.h>
#include "libavformat/avformat.h"
#include <libavfilter/avfilter.h>
#include <jni.h>

JNIEXPORT jstring Java_com_righere_ffmpegndkbuild_MainActivity_avcodecInfo(JNIEnv* env, jobject obj)
{
    char info[4000] = { 0 };
    int count = 100;  //输出前100个codec名字
    
    av_register_all();//初始化所有decoder和encoder,注册所有容器类型和codec
    
    AVCodec *c_temp = av_codec_next(NULL);

    while (c_temp != NULL && count > 0){
        //输出解码器和编码器
        if(c_temp->decode != NULL){
            sprintf(info,"%s[Dec]",info);
        }
        else{
            sprintf(info,"%s[Enc]",info);
        }
        
        sprintf(info,"%s[%10s]\n",info,c_temp->name);
        
        c_temp = c_temp->next;
        count--;
    }
    return (*env)->NewStringUTF(env, info);
 }

修改gradle(修改的是app的build.gradle)

  • 告诉gradle,.mk文件的路径(在android{–}里面添加):
    externalNativeBuild {
        ndkBuild {
            path 'src/main/jni/Android.mk'
        }
    }
  • 告诉gradle,完成编译之后,我们的生成的.so文件在哪个目录下面(在android{–}里面添加):

这里我编译的armeabi版本的生成的.so文件自动会放在了’src/main/libs/armeabi’这个目录下面,其他的版本只需要把armeabi名字变一下就行了

    sourceSets.main {
        jni.srcDirs = [] //disable automatic ndk-build
        jniLibs.srcDirs = ['src/main/libs/armeabi']
    }
  • 告诉gradle,ndk-build的时候还要执行哪些附加选项(在defaultConfig{}里面添加):

这一步其实可以看做是对.mk文件的补充

    ndk {
            abiFilter "abiFilter "     //在Application.mk里面设置保持一致,如果是编译了多个平台的,可以指定编译多平台的或者
            moduleName "FFmpegCodec"    //jni模块的名字,与android.mk文件保持一致
            ldLibs "log", "z", "m", "jnigraphics", "android"    //这里可以设置ldLibs选项,比如你想调试jni的时候必须添加"log"参数

        }

执行ndk-build

编译完成main文件夹下会增加libsobj两个文件夹,其中libs/armeabi下就是我们需要的.so文件

├── jni
│   ├── Android.mk
│   ├── Application.mk
│   ├── ffmpeg-jni.c
│   ├── include
│   └── lib
├── libs
│   └── armeabi
├── obj
│   └── local
└── res

切换回Android结构的工程试图,系统会自动把生成的.so文件放入jniLibs中,看到这个FFmpeg的移植基本就成功了

测试FFmpeg移植

在MainActivity中添加测试代码,

public class MainActivity extends AppCompatActivity {
    //jni
   public native String avcodecInfo();

    static {
        System.loadLibrary("FFmpegCodec");
        System.loadLibrary("avcodec");
        System.loadLibrary("avfilter");
        System.loadLibrary("avformat");
        System.loadLibrary("avutil");
        System.loadLibrary("swresample");
        System.loadLibrary("swscale");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView Codec_info = (TextView) findViewById(R.id.TextView_codec_info);
        Codec_info.setMovementMethod(ScrollingMovementMethod.getInstance());
        Codec_info.setText(avcodecInfo());
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ffmpeg交叉编译移植是将ffmpeg库从一个平台编译移植到另一个平台的过程。这个过程可以让我们在目标平台上运行ffmpeg库,并使用其功能。 要进行ffmpeg交叉编译移植,可以按照以下步骤进行操作: 1. 确定目标平台和编译环境。 在交叉编译移植之前,需要确定目标平台的操作系统和架构,并准备好相应的编译环境。例如,如果目标平台是ARM架构的嵌入式设备,需要安装适用于ARM平台的交叉编译工具链。 2. 获取ffmpeg源代码。 可以从FFmpeg的官方GitHub存储库中获取ffmpeg的源代码。使用git clone命令或直接下载源代码压缩包来获取代码。 3. 配置编译选项。 进入ffmpeg源代码目录,并使用configure命令来配置编译选项。根据目标平台和需求,选择适当的选项进行配置。可以参考FFmpeg的官方文档或者之前成功移植的经验来确定合适的选项。 4. 进行交叉编译。 在完成配置后,使用make命令进行交叉编译。根据编译环境的不同,可能需要使用特定的编译选项或命令来进行交叉编译。可以参考之前成功移植的经验或相关的教程来进行操作。 5. 测试和调试。 在编译完成后,将生成的ffmpeg移植到目标平台上,并进行测试和调试。可以使用一些示例代码或自己编写的代码来测试ffmpeg库的功能和性能。 请注意,由于不同的平台和需求,ffmpeg的交叉编译移植可能会有一些特定的问题和挑战。在遇到问题时,可以参考相关的文档、教程和社区讨论来获取帮助和解决方案。引用提供了一些关于在Windows平台上编译带有libx264和libmp3lame的FFmpeg库的详细步骤,可以参考这些资源来获取更具体的信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值