安卓下编译及修剪FFMPEG插件

按照特定需求修剪

Posted by MetaNetworks on December 7, 2020
本页面总访问量

Android下编译及修剪FFMPEG插件

FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。它包括了目前领先的音/视频编码库libavcodec。 FFmpeg是在 Linux 下开发出来的,但它可以在包括 Windows 在内的大多数操作系统中编译。这个项目是由 Fabrice Bellard 发起的,现在由 Michael Niedermayer 主持。可以轻易地实现多种视频格式之间的相互转换,例如可以将摄录下的视频avi等转成现在视频网站所采用的flv格式。

提要

FFMPEG确实是一个神器,支持各种格式,如果嵌入应用的话,遇到的问题就很明显:体积太大

一个大致完整的FFMPEG插件的大小有将近200MB emm,而需求往往只需要特定一些功能,所以裁剪是个必不可少的需求。

下载源代码

可以到FFMPEG官网下载,但与其下载源码自己改,不妨下载安卓适配的mobile-ffmpeg,该插件也存在FFMPEG官网中,是个官方认可的三方编译插件,且star有2.4k。

值得注意的是:FFMPEGLGPL/GPL项目,如果要用在商业用途,请一定避免使用--enable-gpl以及--enable-nonfree,若要修改FFMPEG代码,则必须声明修改部分!否则容易引起版权问题!

此处以mobile-ffmpeg为例说明。

明确需求

此处假定一个最简单的需求:要求将aac格式的音频文件转为特定码率,特定采样率,1声道的pcm_s16le原生格式的音频文件。那么我们只需要保留此功能即可。

修剪

mobile-ffmpeg中使用android.sh进行安卓版本的编译,若要修剪,则需要修改configure的参数,build/android-ffmpeg.sh配置了configure参数。

在该文件找到configure参数,在尾部加上:

1
2
3
4
5
6
7
8
--disable-everything
--enable-filter=anull,aresample,aformat \
--enable-parser=aac* \
--enable-demuxer=aac* \
--enable-muxer=pcm_s16le \
--enable-decoder=aac*,pcm_s16le \
--enable-protocol=file \
--enable-encoder=pcm_s16le \

首先使用--disable-everything关掉所有的组件,再添加需要的内容

  • encoder
    • 为编码器,由于只需要一种pcm_s16le,则只开这个即可
  • decoder
    • 为解码器,作用于源文件,由于只需要aac(aac也含有多种子类型)格式,此处改为aac*,匹配所有类型的aac
  • parser
    • 为解释器,每一个解码器/编码器都需要一个parser从输入中获取一帧数据,所以此处需要同时支持encoder和decoder的类型,为aac*,pcm_s16le
  • muxer
    • 为合并器,可以将视频和音频数据合并到一个封装格式数据中去。此处也加一个pcm_s16le
  • demuxer
    • 为分离器,可以将文件拆分,如rmvb中含有视频和字幕文件时,可以用这个进行分离。对于封装的格式也有拆分的作用。作用于源文件。
  • muxer
    • 与demuxer相反。作用于目标文件。此处为pcm_s16le
  • protocol
    • 支持输入输出的协议,由于只是文件操作,所以这直接为file
  • filter
    • 是对音频/视频做变换的组件,改码率,声道,指定格式要用到,此处测试过用anull,aresample,aformat即可(a表示音频滤镜)
      • anull即直接将源输入导出至输出
      • aresample表示重新采样
      • aformat用于约束目标文件的格式

之后进行编译,编译日志会出现在build.log中,如果遇到错误可以这样改

编译失败,如果是说NDK版本不完全一致,可以在app/build.gradle

进一步修剪

此时发现已经很小(1MB)了,能否进一步改呢?

我们发现在configure下有个选项还是开着的

1
--enable-swscale

scale为缩放的意思SoftWare Scale。但是处理音频的话,也不变速,所以直接改为--diable-swscale。进行编译…

发现编译不通过,查看build.log提示swscale啥的不存在。奇怪了,视频组件为啥要依赖到cpp层…开始改c++代码。

首先查看报错的android/jni/Android.mk文件,发现引用了libswscale.so,注释掉

1
2
3
4
5
#include $(CLEAR_VARS)
#LOCAL_ARM_MODE := $(MY_ARM_MODE)
#LOCAL_MODULE := libswscale
#LOCAL_SRC_FILES := libswscale.so
#include $(PREBUILT_SHARED_LIBRARY)

再逐步编译,查看哪里错误,把相关代码或函数注释掉…

最后也能减小将近200KB的sdk大小。