FFmpeg编译与集成

2023-11-13

Java是 write once,run anywhre,但 C 不一样,各平台均有差异,无法只写一次,而且各个平台的编译都不一样。比如android的ndk工具链,不同平台的库都是不一样的

本文主要讲解下 ffmpeg 在 win 平台下的编译以及集成

1、交叉编译

交叉编译:交叉编译就是程序的编译环境和实际运行环境不一致,即在一个平台上生成另一个平台上的可执行代码。

为什么要交叉编译,其实之前原因已经说过了,因为不同平台的差异,指令集都不一样,比如win上面是intel的指令集,但android手机上几乎百分百都是arm的指令集,所以直接拿win上编译出来的库给android用,肯定无法使用的,所以需要交叉编译。

交叉编译主要是借助android 的ndk工具包

下面大致列举了一下经常会用到的组件。

  • ARM 交叉编译器

  • 构建工具

  • Java 原生接口头文件

  • C 库

  • Math 库

  • 最小的 C++ 库

  • ZLib 压缩库

  • POSIX 线程

  • Android 日志库

  • Android 原生应用 API

  • OpenGL ES 库

  • OpenSL ES 库

下面来看一下 Android 所提供的 NDK 跟目录下的结构。

  • ndk-build: 该 Shell 脚本是 Android NDK 构建系统的起始点,一般在项目中仅仅执行这一个命令就可以编译出对应的动态链接库了。

  • ndk-gdb: 该 Shell 脚本允许用 GUN 调试器调试 Native 代码,并且可以配置到 AS 中,可以做到像调试 Java 代码一样调试 Native 代码。

  • ndk-stack: 该 Shell 脚本可以帮组分析 Native 代码崩溃时的堆栈信息。

  • build: 该目录包含 NDK 构建系统的所有模块。

  • platforms: 该目录包含支持不同 Android 目标版本的头文件和库文件, NDK 构建系统会根据具体的配置来引用指定平台下的头文件和库文件。

  • toolchains: 该目录包含目前 NDK 所支持的不同平台下的交叉编译器 - ARM 、X86、MIPS ,目前比较常用的是 ARM 。构建系统会根据具体的配置选择不同的交叉编译器。

toolchains里一般会提供这么一些工具:

  • CC:编译器,对C源文件进行编译处理,生成汇编文件。

  • AS:将汇编文件生成目标文件(汇编文件使用的是指令助记符,AS将它翻译成机器码)。

  • AR:打包器,用于库操作,可以通过该工具从一个库中删除或者增加目标代码模块。

  • LD:链接器,为前面生成的目标代码分配地址空间,将多个目标文件链接成一个库或者是可执行文件。

  • GDB:调试工具,可以对运行过程中的程序进行代码调试工作。

  • STRIP:以最终生成的可执行文件或者库文件作为输入,然后消除掉其中的源码。

  • NM:查看静态库文件中的符号表。

  • Objdump:查看静态库或者动态库的方法签名。

不过不同版本的ndk,里边的工具不一样,部分新的ndk里可能就没有ar 、strip 之类的,可能在新的ndk里这些工具命名不一样或者是放在其它地方了,比如本人发现的21.1.6352462(win)中包含 strip 和 ar,但 24.0.8215888 版本中没有相关库,而且这几个版本中都没有 nm 库,在编译 ffmpeg时一定会提示找不到nm,幸好 nm不是必须的,不慌,如果遇到找不到相关工具,说明路径设置的有问题,或者根本就是当前版本的ndk中没有此类工具或者已经改名,需要去找找资料看看新版本的工具叫啥或者干脆下载旧版本ndk

 【学习地址】:FFmpeg/WebRTC/RTMP/NDK/Android音视频流媒体高级开发https://link.zhihu.com/?target=https%3A//ke.qq.com/course/3202131%3FflowToken%3D1042495 【文章福利】:免费领取更多音视频学习资料包、大厂面试题、技术视频和学习路线图,资料包括(C/C++,Linux,FFmpeg webRTC rtmp hls rtsp ffplay srs 等等)有需要的可以点击1079654574加群领取哦~

2、FFmpeg编译

一名优秀的c++开发,必须得对c++编译有一定了解。前文已经介绍了交叉编译,那现在就来学习如何编译 ffmpeg 吧

在ffmpeg官网下载源码:

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

根据自己需要,切换自己想要的版本。

ffmpeg的编译其实已经非常简单了,因为牛逼的ffmpeg开发者提供了一个脚本,叫 configure,其实我们写的编译脚本就是在指定编译工具的位置,然后调用 configure 脚本编译

本人是在win11上编译 ffmpeg,需要下载msys2工具并配置相关环境,必须以管理员运行msys2之后才能来配置环境,否则就会报异常

pacman -S make yasm diffutils pkg-config #在msys2上安装必要软件

然后在ffmpeg文件夹内建脚本文件,并把如下内容贴上:

 #!/bin/sh
​
NDK_PATH=/c/workspace/android_sdk/ndk/21.1.6352462
​
BUILD_PLATFORM=windows-x86_64
​
API=21
​
ANDROID_ARMV5_CFLAGS="-march=armv5te"
ANDROID_ARMV7_CFLAGS="-march=armv7-a -mfloat-abi=softfp -mfpu=neon"
ANDROID_ARMV8_CFLAGS="-march=armv8-a"
ANDROID_X86_CFLAGS="-march=i686 -mtune=intel -mssse3 -mfpmath=sse -m32"
ANDROID_X86_64_CFLAGS="-march=x86-64 -msse4.2 -mpopcnt -m64 -mtune=intel"
​
​
# params($1:arch,$2:arch_abi,$3:compiler,$4:cross_prefix,$5:cflags)
build_bin() {
​
    echo "-------------------star build $2-------------------------"
​
    ARCH=$1         # arm arm64 x86 x86_64
    # CPU
    ANDROID_ARCH_ABI=$2     # armeabi armeabi-v7a x86 mips
​
    COMPILER=$3
​
    PREFIX=$(pwd)/dist/${ANDROID_ARCH_ABI}/
​
    TOOLCHAIN=${NDK_PATH}/toolchains/llvm/prebuilt/${BUILD_PLATFORM}
​
    CC=${TOOLCHAIN}/bin/${COMPILER}-clang
​
    CXX=${TOOLCHAIN}/bin/${COMPILER}-clang++
​
    SYSROOT=${TOOLCHAIN}/sysroot
​
    CROSS_PREFIX=${TOOLCHAIN}/bin/$4-
​
    CFLAGS=$5
​
    echo "pwd==$(pwd)"
    echo "ARCH==${ARCH}"
    echo "PREFIX==${PREFIX}"
    echo "SYSROOT=${SYSROOT}"
    echo "CFLAGS=${CFLAGS}"
    echo "CC==${CC}"
    echo "CROSS_PREFIX=${CROSS_PREFIX}"
​
    sh ./configure \
        --prefix=${PREFIX} \
        --enable-neon \
        --enable-hwaccels \
        --enable-gpl \
        --disable-postproc \
        --disable-debug \
        --enable-small \
        --enable-jni \
        --enable-mediacodec \
        --enable-decoder=h264_mediacodec \
        --disable-static \
        --enable-shared \
        --disable-doc \
        --enable-ffmpeg \
        --disable-ffplay \
        --disable-ffprobe \
        --disable-avdevice \
        --disable-doc \
        --disable-symver \
        --target-os=android \
        --arch=${ARCH} \
        --cc=$CC \
        --sysroot=$SYSROOT \
        --enable-cross-compile \
        --cross-prefix=${CROSS_PREFIX} \
        --extra-cflags="-Os -fPIC -DANDROID -Wfatal-errors -Wno-deprecated $CFLAGS" \
        --extra-cxxflags="-D__thumb__ -fexceptions -frtti" \
        --extra-ldflags="-L${SYSROOT}/usr/lib" \
​
    make clean
    make -j8
    make install
​
​
    echo "-------------------$2 build end-------------------------"
}
​
​
# build armeabi
# build_bin arm armeabi arm-linux-androideabi arm-linux-androideabi "$ANDROID_ARMV5_CFLAGS"
​
#build armeabi-v7a
#build_bin arm armeabi-v7a armv7a-linux-androideabi${API} arm-linux-androideabi "$ANDROID_ARMV7_CFLAGS"
​
#build arm64-v8a
 build_bin arm64 arm64-v8a aarch64-linux-android${API} aarch64-linux-android "$ANDROID_ARMV8_CFLAGS"
​
#build x86
# build_bin x86 x86 i686-linux-android${API} i686-linux-android "$ANDROID_X86_CFLAGS"
​
#build x86_64
# build_bin x86_64 x86_64 x86_64-linux-android${API} x86_64-linux-android "$ANDROID_X86_64_CFLAGS"

相关解释:

  • CC:指定c编译器路径

  • CROSS_PREFIX:指定交叉编译工具文件路径的统一前缀。各个工具的最终文件路径为:cross-prefix + 工具名,比如上面脚本的prefix为TOOLCHAIN/bin/arm-linux-androideabi-,那么ar工具的路径即为TOOLCHAIN/bin/arm-linux-androideabi-ar

  • target-os:指定目标平台,因为 ffmpeg 可以在各平台上运行的,各平台上一些配置不太一样,所以需要指定的

另外编译脚本里边还有大量的 enable disable ,这些都是 configure 脚本里的编译选项,比如说 --enable-shared 意思就是编译动态库,所以上面的脚本最终会生成 so 文件,而不会生成 a 文件。

这些编译选项都可以使用 configure --help,可以查询到,大家可以试试

不管是这些 enable 编译选项,还是像 CC 一类的选项,都是在配置 configure 脚本,通过文本方式打开 configure 文件,可以看到:

--cc=CC                  use C compiler CC [$cc_default]
--target-os=OS           compiler targets OS [$target_os]
--enable-shared          build shared libraries [no]

运行编译脚本之后,如果编译成功了就会看到相关so库了,so库在lib文件夹中

3、FFmpeg集成

首先看cmakelist怎么写:

# 设置最小使用版本
cmake_minimum_required(VERSION 3.18.1)
​
project("demo")
​
include_directories(include)
​
# 添加本地so库 native-lib:这个是声明引用so库的名称 SHARED:表示共享so库文件
# 构建so库的源文件
add_library(
        demo
        SHARED
        native-lib.cpp
)
​
set(SO_DIR ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})
​
# 使用系统ndk 提供的库,如 log库
# log-lib 这个指定的是在NDK库中每个类型的库会存放一个特定的位置,而log库存放
# 在log-lib中
# log 指定使用log库
find_library(
        log-lib
        log
)
​
message("c_CMAKE_SOURCE_DIR:" ${CMAKE_SOURCE_DIR} )
​
# 加载avcodec-57库
add_library( avcodec
        SHARED
        IMPORTED)
set_target_properties( avcodec
        PROPERTIES IMPORTED_LOCATION
        ${SO_DIR}/libavcodec.so)
​
add_library( avutil
        SHARED
        IMPORTED)
set_target_properties( avutil
        PROPERTIES IMPORTED_LOCATION
        ${SO_DIR}/libavutil.so)
​
add_library( swresample
        SHARED
        IMPORTED)
set_target_properties( swresample
        PROPERTIES IMPORTED_LOCATION
        ${SO_DIR}/libswresample.so)
​
add_library( avfilter
        SHARED
        IMPORTED)
set_target_properties( avfilter
        PROPERTIES IMPORTED_LOCATION
        ${SO_DIR}/libavfilter.so)
​
add_library( avformat
        SHARED
        IMPORTED)
set_target_properties( avformat
        PROPERTIES IMPORTED_LOCATION
        ${SO_DIR}/libavformat.so)
​
add_library( swscale
        SHARED
        IMPORTED)
set_target_properties( swscale
        PROPERTIES IMPORTED_LOCATION
        ${SO_DIR}/libswscale.so)
#----------------------end-----------------------
​
# 如果你本地的库(native-lib)想要调用log库的方法,
# 那么就需要配置这个属性,意思是把NDK库关联到本地库。
# 第一个参数表示本地的库 native-lib 要调用到log库的方法,即要被关联的库名称,log-lib 要关联的库名称
target_link_libraries(
        demo
        #ffmpeg------start----------
        avcodec
        avutil
        swresample
        avfilter
        avformat
        swscale
        #ffmpeg------end------------
        ${log-lib}
)

其实这些写法都非常简单,如果出错肯定是没写对,注意下相关细节即可。 所有代码均已上传到本人github中

原文链接:FFmpeg编译与集成 - 掘金

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FFmpeg编译与集成 的相关文章

随机推荐

  • 匿名内部类在开发中的真实使用场景演示

    package Java project 1 import javax swing import java awt event ActionEvent import java awt event ActionListener public
  • linux开启使用ftp

    一 检查系统是否安装vsftpd rpm qa grep vsftpd 这里是安装好了 才会出现版本信息 没有安装不会出现 如果想删除卸载vsftpd使用 rpm qa grep vsftpd 查询出来版本好 通过 rpm e vsftpd
  • libuv使用总结

    libuv是单线程的 依靠uv run轮训当前线程关心的事件IO 所以这些函数的回调里尽量不要有阻塞的函数 否则回调之间相互影响 导致另外的回调走不到 libuv如果使用不当 会造成coredump 多线程用多线程的接口 单线程用单线程的接
  • jemalloc原理分析

    jemalloc原理分析 转载自http club alibabatech org article detail htm articleId 36 首先介绍一下jemalloc中的几个核心概念 1 arena jemalloc的核心分配管理
  • Android中应用程序清除data/data,清除缓存,兼容8.0系统

    前言 最近实现了一款系统级应用中心 需要获取已安装APP的缓存大小以及清除缓存 获取缓存的在另外一篇博客总结过 获取APP缓存大小 因此这篇文章记录一下如何清除缓存 一 安卓8 0之前 1 首先需要自己创建几个AIDL文件 方法在前言连接里
  • 多线程之实现Callable接口

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 调用方法 点击量 月 年 Callable public void yearlyClickCallable 获取参数 String year getPara year 统计
  • 3-13反思总结

    1 innerHTML 修改 HTML 内容的最简单的方法是使用 innerHTML 属性 这句话的说法是错误的 innerHTML属性用于获取或替换 HTML 元素的内容 不能用来修改内容 2 null与undifined 1 null
  • k8s,30分钟部署一个kubernetes集群【1.17】

    作者 李振良 官方网站 http www ctnrs com kubeadm是官方社区推出的一个用于快速部署kubernetes集群的工具 这个工具能通过两条指令完成一个kubernetes集群的部署 创建一个 Master 节点 kube
  • Java如何读取文件文本内容的几种方式汇总

    本文为joshua317原创文章 转载请注明 转载自joshua317博客 Java如何读取文件文本内容的几种方式汇总 joshua317的博客 package com joshua317 import java io import jav
  • Python爬虫学习笔记(三)————urllib

    目录 1 使用urllib来获取百度首页的源码 2 下载网页图片视频 3 总结 1 4 请求对象的定制 解决第一种反爬 5 编解码 1 get请求方式 urllib parse quote 2 get请求方式 urllib parse ur
  • java复制文件的4种方式及拷贝文件到另一个目录下的实例代码

    这篇文章主要介绍了java复制文件的4种方式 通过实例带给大家介绍了java 拷贝文件到另一个目录下的方法 需要的朋友可以参考下 尽管Java提供了一个可以处理文件的IO操作类 但是没有一个复制文件的方法 复制文件是一个重要的操作 当你的程
  • 在计算机中安装深度操作系统

    深度操作系统是一个国产的Linux发行版 界面美观 系统友好 中文支持完善 易上手 对于Linux新手来说 是一个不错的操作系统 这里将我安装深度操作系统的过程复述一下 在这里 我用的是UEFI GPT的方式来安装的 安装准备 一张容量足够
  • js弹出弹窗,并从弹窗中取值,返回父页面

    弹出弹框 url pageContext request contextPath facegl eyecool eyecool jsp pqdwbmid pqdwbmid rytype rytype open win window open
  • 数字IC设计笔试面试经典题(1-10)

    1 基础知识 1 1 锁存器的结构 锁存器即Latch 数电中称之为电平触发的D触发器 也是D型锁存器 有电平触发器SR触发器改进得到 其工作特点是电平是有效电平 高电平或者低电平 期间 才接受信号并输出 否则保持不变 1 2 DFF的结构
  • ctf(一):攻防世界

    网址 https adworld xctf org cn 1 post传参 2 get传参直接在后面加 id 1 3 robots txt 文件 直接在网址后面加 robots txt 就会显示后台文件 4 index php 后缀是 ph
  • C++类中this指针的理解

    https www cnblogs com liushui sky p 5802981 html 很好的文
  • 中国国家气象局天气预报信息接口

    想在自己的android应用中获得当天的天气情况 这该怎么做呢 不用担心 中国国家气象局提供了获取所在城市天气预报信息接口 通过这个接口 我们就可以获取天气信息了 中国国家气象局天气预报接口总共提供了三个 http www weather
  • 【人工智能业务概述】—人工智能的技术框架

    人工智能业务概述 人工智能的技术框架 人工智能的技术框架按照产业生态通常可以划分为基础层 技术层 应用层三大板块 其中 基础层提供了支撑人工智能应用的基础设施和技术 包括存储和处理大规模数据的能力 以及高性能的计算和通信基础设施 技术层提供
  • 怎么查看华为服务器型号,云服务器型号查看

    云服务器型号查看 内容精选 换一换 华为云帮助中心 为用户提供产品简介 价格说明 购买指南 用户指南 API参考 最佳实践 常见问题 视频帮助等技术文档 帮助您快速上手使用华为云服务 根据后端云服务器组的ID查询后端云服务器组详情 GET
  • FFmpeg编译与集成

    Java是 write once run anywhre 但 C 不一样 各平台均有差异 无法只写一次 而且各个平台的编译都不一样 比如android的ndk工具链 不同平台的库都是不一样的 本文主要讲解下 ffmpeg 在 win 平台下