NDK R25b 交叉编译FFMpeg4,项目集成,附库下载地址

1.准备工作

文件下载:

NDK R25b下载地址:Android NDK历史版本下载网址 - 君*邪 - 博客园 (cnblogs.com)

FFmpeg4.4.4 下载地址:https://ffmpeg.org/releases/ffmpeg-4.4.4.tar.xz

环境配置:

本次编译环境是在PC虚拟机中使用Ubuntu18.04

在这里插入图片描述

下载好NDK和FFmpeg 之后,复制到Ubuntu下然后解压,为交叉编译做准备

2.交叉编译FFmpeg流程

解压完FFmpeg源码之后,进入源码根目录,新建编译脚本android.sh

在这里插入图片描述

新版 ndk 已放弃 gcc,转而使用更高效的 clang,下述脚本以 clang 为例编译 FFmpeg 源码。支持编译armv8-a 和armv7-a,注意修改成你的NDK目录地址

 #!/bin/bash# 修改成你的NDK目录TOOLCHAIN=/home/marxist/ndk/android-ndk-r25b-linux/android-ndk-r25b/toolchains/llvm/prebuilt/linux-x86_64# 最低支持的android sdk版本API=21function build_android{echo "Compiling FFmpeg for $CPU"./configure \--prefix=$PREFIX \--enable-neon \--enable-shared \--enable-small \--disable-vulkan \--disable-gpl \--disable-postproc \--disable-jni \--disable-mediacodec \--disable-decoder=h264_mediacodec \--disable-static \--disable-doc \--disable-programs \--disable-ffmpeg \--disable-ffplay \--disable-ffprobe \--disable-avdevice \--disable-symver \--enable-cross-compile \--cross-prefix=$CROSS_PREFIX \--target-os=android \--arch=$ARCH \--cpu=$CPU \--cc=$CC \--cxx=$CXX \--sysroot=$SYSROOT \--extra-cflags="-mno-stackrealign -Os -fpic -mfpu=neon $OPTIMIZE_CFLAGS" \--extra-ldflags="$ADDI_LDFLAGS"#--disable-debug#--disable-stripping#--disable-linux-perf#--disable-hwaccelsmake cleanmake -j4make installecho "The Compilation of FFmpeg for $CPU is completed"}function print_supported_cpus{echo "Supports the following CPUs:"echo "1. armv7-a"echo "2. armv8-a"}function print_usage{echo "Usage: $0 [CPU]"echo "Example: $0 armv7-a"print_supported_cpus}# 传入CPU参数CPU=$1if [ -z "$CPU" ]; thenprint_usageexit 1elif [ "$CPU" = "help" ]; thenprint_usageelif [ "$CPU" = "armv7-a" ]; thenARCH=armCC=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clangCXX=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang++SYSROOT=$TOOLCHAIN/sysrootCROSS_PREFIX=$TOOLCHAIN/bin/llvm-PREFIX=$(pwd)/android/$CPUADDI_LDFLAGS=" "OPTIMIZE_CFLAGS="-mfloat-abi=softfp -march=$CPU"build_androidelif [ "$CPU" = "armv8-a" ]; thenARCH=arm64CC=$TOOLCHAIN/bin/aarch64-linux-android$API-clangCXX=$TOOLCHAIN/bin/aarch64-linux-android$API-clang++SYSROOT=$TOOLCHAIN/sysrootCROSS_PREFIX=$TOOLCHAIN/bin/llvm-PREFIX=$(pwd)/android/$CPUOPTIMIZE_CFLAGS="-march=$CPU"build_androidelseecho "Unsupported CPU: $CPU"print_supported_cpusfi

环境设置

  • TOOLCHAIN: 指向 NDK 中包含的 LLVM 工具链的路径。这个路径用于定位编译工具(如 clang)和系统根目录。
  • API: 设置编译目标的最低 Android API 级别。

函数定义

  1. build_android

    • 打印正在为特定 CPU 架构编译 FFmpeg。
    • 运行 FFmpeg 的 ./configure 脚本来配置编译选项。
    • 调用 make clean 清理之前的构建结果。
    • 使用 make -j4 启动并行编译过程。
    • 调用 make install 将编译结果安装到指定的前缀路径 $PREFIX
    • 打印完成编译的消息。
  2. print_supported_cpus

    • 打印支持的 CPU 类型。
  3. print_usage

    • 打印脚本的使用方法。

主体逻辑

  • 脚本接收一个参数($1),即 CPU 类型。
  • 根据传入的 CPU 类型,设置相关的编译参数:
    • ARCH: 指定目标架构。
    • CCCXX: 指定 C 和 C++ 编译器。
    • SYSROOT: 设置系统根目录。
    • CROSS_PREFIX: 设置交叉编译工具前缀。
    • PREFIX: 指定安装目录。
    • ADDI_LDFLAGS: 设置额外的链接器标志。
    • OPTIMIZE_CFLAGS: 设置针对特定 CPU 优化的编译标志。
  • 调用 build_android 函数开始编译流程。

详细配置参数(./configure)

  • --prefix=$PREFIX: 指定安装路径。
  • --enable-neon, --enable-shared, --enable-small: 启用 ARM NEON 指令集支持,生成共享库,优化库大小。
  • --disable-...: 禁用多个功能,如 Vulkan, GPL 功能,文档生成等。
  • --enable-cross-compile: 启用交叉编译模式。
  • --cross-prefix=$CROSS_PREFIX: 设置交叉编译前缀。
  • --target-os=android: 设置目标操作系统为 Android。
  • --arch=$ARCH: 设置目标架构。
  • --cpu=$CPU: 设置目标 CPU。
  • --cc=$CC, --cxx=$CXX: 设置 C 和 C++ 编译器。
  • --sysroot=$SYSROOT: 设置系统根目录。
  • --extra-cflags: 设置额外的编译标志,主要用于性能优化和适应特定硬件。
  • --extra-ldflags: 设置额外的链接标志。

编译成功之后,在源码目录的android文件夹生成目标CPU的so库和相关的头文件,libavcodec.so libavformat.so libswresample.so libavfilter.so libavutil.so

在这里插入图片描述

如果需要其他的so 注释掉编译脚本的disable 就能生成对应的其他库

3.Android项目集成FFmpeg库

在项目main文件夹新建 ThirdLib文件夹,根据需求添加不同CPU架构下的so库,这里主要是添加了arm64v8-a的库(在ThirdLib文件夹新建arm64-v8a 文件夹,方便与CMakeLists.txt做对应)

在cpp文件夹新建include文件夹,将FFmpeg头文件放入进去,头文件编译的时候会生成。

在这里插入图片描述

项目目录层级如上图所示,ThirdLib文件夹与cpp文件夹同一目录,include文件夹与CMakeLists.txt同一目录。如果所有设置都与我一致,就可以直接copy CMakeLists.txt

接下来就是配置CMakeLists.txt

引入FFmpeg 头文件,添加FFmpeg相关的库

# Include directories
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)add_library(avcodec SHARED IMPORTED)
set_target_properties(avcodec PROPERTIES IMPORTED_LOCATION${CMAKE_SOURCE_DIR}/../ThirdLib/arm64-v8a/libavcodec.so)
add_library(avfilter SHARED IMPORTED)
set_target_properties(avfilter PROPERTIES IMPORTED_LOCATION${CMAKE_SOURCE_DIR}/../ThirdLib/arm64-v8a/libavfilter.so)
add_library(avformat SHARED IMPORTED)
set_target_properties(avformat PROPERTIES IMPORTED_LOCATION${CMAKE_SOURCE_DIR}/../ThirdLib/arm64-v8a/libavformat.so)
add_library(avutil SHARED IMPORTED)
set_target_properties(avutil PROPERTIES IMPORTED_LOCATION${CMAKE_SOURCE_DIR}/../ThirdLib/arm64-v8a/libavutil.so)
add_library(swresample SHARED IMPORTED)
set_target_properties(swresample PROPERTIES IMPORTED_LOCATION${CMAKE_SOURCE_DIR}/../ThirdLib/arm64-v8a/libswresample.so)
add_library(swscale SHARED IMPORTED)
set_target_properties(swscale PROPERTIES IMPORTED_LOCATION${CMAKE_SOURCE_DIR}/../ThirdLib/arm64-v8a/libswscale.so)

编译的时候链接库, firstjni是我的项目名称,不同项目名称自动生成不同的名字,主要是添加五个库

#编译链接库
target_link_libraries( # Specifies the target library.firstjniavcodecavfilteravformatavutilswresampleswscale# Links the target library to the log library# included in the NDK.${log-lib})

4.示例代码,获取FFmpeg版本

在MainActivity生成JNI函数接口

 public native String getFFMpegVersion();

使用Android Studio自动创建相应的c++实现

native-lib.cpp 引入FFmpeg头文件

extern "C"{
#include <libavutil/avutil.h>
}

实现接口,获取FFMpeg当前版本

extern "C"
JNIEXPORT jstring JNICALL
Java_com_marxist_firstjni_MainActivity_getFFMpegVersion(JNIEnv *env, jobject thiz) {// TODO: implement getFFMpegVersion()const char *ffmpeg_version = av_version_info();return env->NewStringUTF(ffmpeg_version);
}

效果如图: 输出了4.4.4

在这里插入图片描述

5.资源下载

提供armv7 和 armv8两个版本

编译平台:NDK R25b

FFmpeg版本: 4.4.4

链接:https://pan.baidu.com/s/1PH6bVRv8_0hda-VjesoRyw
提取码:c0rc

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3246501.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

BigMarker-抽奖前置规则过滤

需求 在我们的流程设计中&#xff0c;用户执行抽奖时会判断是否已经超过N积分&#xff0c;如果超过N积分则可以在限定范围内进行抽奖。同时如果用户是黑名单范围的羊毛党用户&#xff0c;则只返回固定的奖品ID 模型 整个规则来说&#xff0c;分为抽奖前、抽奖中、抽奖后&#…

无人机之机型区别与应用领域

一、多旋翼无人机 特点&#xff1a;多旋翼无人机依靠产生升力以平衡飞行器的重力&#xff0c;通过改变每个旋翼的转速来控制飞行姿态&#xff0c;能够悬停和垂直起降。他们具备体积小、重量轻、噪音小、隐蔽性好的特点&#xff0c;操作灵活且易于维护。 应用&#xff1a;多旋…

数据库(创建数据库和表)

目录 一&#xff1a;创建数据库 二&#xff1a;创建表 2.1&#xff1a;创建employees表 2.2&#xff1a;创建orders表 2.3&#xff1a;创建invoices表 一&#xff1a;创建数据库 mysql> create database mydb6_product; Query OK, 1 row affected (0.01 sec) mysql&g…

排序——归并排序及排序章节总结

前面的文章中 我们详细介绍了排序的概念&#xff0c;插入排序&#xff0c;交换排序与选择排序&#xff0c;大家可以通过下面的链接再去学习&#xff1a; ​​​​​​排序的概念及插入排序 交换排序 选择排序 这篇文章就详细介绍一下另一种排序算法&#xff1a;归并排序以及…

鼠标宏编辑有什么作用?通用鼠标宏软件下载

你知道鼠标宏编辑吗&#xff1f;鼠标宏编辑是电脑鼠标连点器内一种常用功能。用户通过鼠标宏编辑可以很好提高效率。本文将深入探讨鼠标宏编辑的定义、作用及其在不同领域的应用&#xff0c;带您了解它的重要性和实际价值。并整理了2024年最新款的6大好用鼠标宏软件&#xff0c…

FPGA实训报告DAY 1(Verilog HDL)

实习日志与总结 日期&#xff1a;2024 年 7 月 10 日 星期三 姓名&#xff1a;XXX 一、实习日志 上午 9:00 - 9:30 按时到达工位&#xff0c;参加部门早会&#xff0c;了解了今天的实习任务和目标&#xff0c;即初步学习 FPGA 简介和 Verilog 基础语法知识。 9:30 - 10:30…

大数据基础:Doris重点架构原理

文章目录 Doris重点架构原理 一、Apache Doris介绍 二、Apache Doris使用场景 三、Apache Doris架构原理 四、Apache Doris 特点 Doris重点架构原理 一、Apache Doris介绍 基于 MPP 架构的高性能、实时的分析型数据库&#xff0c;以极速易用的特点被人们所熟知&#xff…

嵌入式人工智能(7-树莓派4B的IIC总线连接OLED显示中文与图片)

1、IIC总线 IIC总线&#xff08;Inter-Integrated Circuit&#xff09;是一种串行通信总线&#xff0c;也被称为I2C总线。它由飞利浦&#xff08;Philips&#xff09;公司在1980年代开发&#xff0c;用于连接微处理器和外部设备。 IIC总线使用两根信号线&#xff1a;SDA&…

【JavaScript 算法】树的遍历:前序、中序与后序

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 一、前序遍历&#xff08;Preorder Traversal&#xff09;前序遍历的步骤前序遍历的JavaScript实现 二、中序遍历&#xff08;Inorder Traversal&#xff09;中序遍历的步骤中序遍历的JavaScript实现 三、后序遍历&#xff…

朴素模式匹配算法与KMP算法(非重点)

目录 一. 朴素模式匹配算法1.1 什么是字符串的匹配模式1.2 朴素模式匹配算法1.3 通过数组下标实现朴素模式匹配算法 二. KMP算法2.1 算法分析2.2 用代码实现&#xff08;只会出现在选择题&#xff0c;考察代码的概率不大&#xff09; 三. 手算next数组四. KMP算法的进一步优化4…

springboot2.x AOP 默认使用Cglib 源码

一、背景 在 SpringBoot 2.x AOP中会默认使用Cglib来实现&#xff0c;但是Spring5中默认还是使用jdk动态代理。Spring AOP 默认使用 JDK 动态代理&#xff0c;如果对象没有实现接口&#xff0c;则使用 CGLIB 代理。也可以强制使用 CGLIB 代理。springboot默认使用cglib实现代码…

在GPU上运行PyTorch

文章目录 1、查看GPU的CUDA版本2、下载CUDA版本3、安装cuDNN4、配置CUDA环境变量5、安装配置Anaconda6、使用Anaconda7、pycharm导入虚拟环境8、安装带GPU的PyTorch⭐9、总结 &#x1f343;作者介绍&#xff1a;双非本科大三网络工程专业在读&#xff0c;阿里云专家博主&#x…

使用assembly插件来将外部文件夹打进jar包

目录&#xff1a; 1、pom文件的配置2、新建assembly的描述文件3、maven打包 1、pom文件的配置 <!--maven构建--><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</ar…

python自动化之用flask校验接口token(把token作为参数)

用到的库&#xff1a;flask 实现效果: 写一个接口&#xff0c;需要token正确才能登录 代码&#xff1a; # 导包 from flask import Flask,request,jsonify,json # 创建一个服务 appFlask(__name__) # post请求&#xff0c;路径&#xff1a;/query app.route(/query, met…

ESP32部署TensorFlow Lite

本来是想找一篇中文教程&#xff0c;不过只看到一个英文官方的&#xff0c;也行吧&#xff0c;虽然效率会慢丢丢。 GitHub - espressif/esp-tflite-micro: TensorFlow Lite Micro for Espressif Chipsets 看了一圈&#xff0c;有个中文的&#xff1a; esp-dl/README_cn.md a…

C语言 ——— 编写代码,判断 整型数组 是否 有序

目录 题目要求 代码实现 题目要求 判断 整型数组 是否有序 如果 整型数组 有序输出 sorted&#xff1b;否则输出 unsorted 代码实现 #include<stdio.h> int main() {int arr[10] { 0 };int sz sizeof(arr) / sizeof(arr[0]);//输入for (int i 0; i < sz; i){s…

5个超牛的Java开源OA项目(强烈推荐)

1. O2OA ——开源地址&#xff1a;https://gitee.com/o2oa/O2OA 概述&#xff1a; O2OA 是一款真正全代码&#xff08;包含服务器、安卓以及IOS客户端&#xff09;开源的企业应用定制化开发平台&#xff0c;适用于企业OA、协同办公类信息化系统的建设和开发。技术&#xff1a;…

【JavaScript 算法】栈与队列:解决括号匹配问题

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 一、算法原理二、算法实现三、应用场景四、总结 在编程中&#xff0c;括号匹配问题是一类常见的算法题&#xff0c;通常用于验证括号的正确性&#xff0c;即检查括号是否成对出现且嵌套正确。栈&#xff08;Stack&#xff0…

Uniapp基础篇(持续更新)

1. Uni-app常用内置组件 view 视图容器 scroll-view 可滚动视图区域&#xff0c;用于区域滚动。需注意在webview渲染的页面中&#xff0c;区域滚动的性能不及页面滚动。 swiper 滑块视图容器。一般用于左右滑动或上下滑动&#xff0c;比如banner轮播图。 image uniapp官方iam…

软件测试——非功能测试

工作职责&#xff1a; 1.负责产品系统测试&#xff0c;包括功能测试、性能测试、稳定性测试、用户场景测试、可靠性测试等。 2.负责测试相关文档的编写&#xff0c;包括测试计划、测试用例、测试报告等。 3.负责自动化测试框架、用例的维护。 岗位要求&#xff1a; 1.熟练…