编译FFmpeg,一个古老的话题,但我还是介绍一遍,就当记录。之前介绍怎么给视频增加水印时,就曾经提到FFmpeg的编译,并且在编译时指定了滤镜的性能。
然而,在手机流行的时代,你可能更须要的是能在iOS或Android平台上运行的FFmpeg,而对于命令行的ffmpeg,你能够在个人电脑下面应用(因为它简洁易操作),也能够在服务程序中应用(装置FFmpeg后间接调用ffmpeg命令),比方小程常常在本人的mac机上应用ffmpeg命令。
本文介绍怎么编译出iOS或Android平台应用的FFmpeg链接库。
正如编译macos平台应用的FFmpeg一样,编译iOS或Android平台应用的FFmpeg,主线也是先configure再make,只不过,有更多的细节须要思考。
我应用的是macos零碎,以下介绍的就是在mac上穿插编译,编译出挪动平台应用的FFmpeg。
(1)编译环境筹备
pkg-config
FFmpeg在编译时常常应用到第三方库(比方x264、rtmp等),编译器在查找这些第三方库的头文件与库文件时,须要应用到程序pkg-config。
pkg-conifig给编译器提供门路与链接选项。第三方库在make install时会生成pc后缀的文件并拷贝到系统目录,而pkg-config就是从这个pc文件读取出门路信息。
能够设置PKG_CONFIG_PATH这个环境变量,指定目录,让pkg-config到这个目录上面去找pc文件,如果不设置,则默认在/usr/local/lib/pkgconfig目录上面查找,比方某个时刻我的pkgconfig目录上面是这样的一堆pc文件:
这样装置pkg-config:
brew install pkg-config
装置pkg-config后,能够这样获取第三方库的门路信息:
pkg-config --cflags --libs freetype2
以下是对于pkg-config命令的一个载图:
须要留神,尽管pkg-config查找到的pc文件外面有记录到第三方动态库的门路,但理论在编译FFmpeg动态库时,并不会链接上这个第三方库,而且在FFmpeg的编译脚本中能够指定第三方库的门路。
freetype
此项只在应用滤镜性能时须要装置。
如果编译时遇到这样的提醒:freetype2 not found using pkg-config,那阐明还没有装置freetype,这样装置即可:
brew install freetype
clang编译器
此项只在编译iOS平台的FFmpeg时才须要。
因为我的mac机曾经装置过xcode,所以clang曾经存在。如果你的mac还没有装置clang的话,那倡议把xcode装置好。
asm编译器
此项只在编译iOS平台的FFmpeg时才须要。
x264或FFmpeg等,都有汇编代码,编译这些汇编代码,须要应用更先进的编译脚本来解决,而mac零碎没有这样的脚本。
这个脚本是gas-preprocessor.pl。
能够这样下载并应用gas-preprocessor.pl:
git clone git://github.com/mansr/gas-preprocessor.gitsudo cp -f gas-preprocessor/gas-preprocessor.pl /usr/local/bin/chmod +x /usr/local/bin/gas-preprocessor.pl
yasm
另一个须要的工具是yasm汇编编译器,能够这样装置:
brew install yasm
NDK工具包
此项只在编译Android平台的FFmpeg时才须要。
能够应用ndk-r9d版本,或者最新的版本,来编译FFmpeg,下载地址: https://developer.android.goo...
(2)FFmpeg源码下载
git clone git://source.ffmpeg.org/ffmpeg.git ffmpeg
(3)编译脚本
不用本人重写了,找开源的我的项目过去批改一下(留神开源协定)就能够了,比方参考这个开源我的项目: https://github.com/yixia/FFmp...
在这个我的项目外面,有编译Android跟iOS平台的相应脚本,而且有相应的优化解决。在挪动平台应用的库都很重视两个货色,一个是性能,另一个是体积大小。一个好的脚本,既要依据不同的硬件类型作编译上的优化,也要依据软件需要裁剪FFmpeg的性能使得进去的库尽可能小(毕竟FFmpeg的性能并非全副都用上)。
(4)脚本批改
小程先介绍一下脚本外面的一些要害参数,这些参数并非平台通用。
指定指令集:
--extra-cflags='-arch armv7s' --extra-ldflags='-arch armv7s'
指定cpu类型:
--arch=arm --cpu=cortex-a9
留神,应该依据不同的指令集应用不同的cpu优化;--arch=arm64,像这样指定具体指令架构也是能够的。
指定零碎:
--target-os=darwin
指定sdk:
--sysroot=/Applications/Xcode.app/.../xxx.sdk
指定编译器:
--cc=xxx/clang
指定库生成目录:
--prefix=build
指定应用的muxer/demuxer/encoder/decoder等:
--enable-muxer=mp4
基本上应用下面介绍的脚本就能够编译了,但有时候也能够作一些批改,比方要退出第三方库时,或者要对某个指令集作优化时,等等。
小程再提一些留神点,有可能帮你解决编译过程中遇到的问题:
--sysroot须要指定。iOS平台为....sdk/,不包含usr/inclue;Android平台是编译链的目录。extra-cflags跟extra-ldflags要指定-arch(iOS)或-march(Android)。在xcode8.3.2(sdk为10.3)上,armv7/armv7s/arm64不能应用"-mfloat-abi=hard"选项,并且arm64要指定-mcpu=cortex-a53。在xcode9.2(sdk为11.2)上,须要--disable-asm。
对于理论我的项目来说,FFmpeg的编译是要害的一步,应该多花工夫去钻研一些要害的细节--性能、性能跟体积大小都很重要。
(5)开始编译与应用
运行脚本即可。最终会生成二进制库,比方iOS个别为动态库(.a文件),而Android个别为动静库(.so文件)。
在编译失去FFmpeg的链接库后,就能够调用它,让它运行起来。这时,须要写本人的调用程序。在这里给出一个简略的调用示例,并且不做代码解释,只是让有须要的读者有一个感知。
extern "C" {#include "libavcodec/avcodec.h"#include "libavformat/avformat.h"}void dump_file_format(const char* filepath) { av_register_all(); av_log_set_level(AV_LOG_DEBUG); AVFormatContext* formatContext = avformat_alloc_context(); AVCodecContext* codecContext = NULL; int status = 0; bool success = false; int audioindex = -1; status = avformat_open_input(&formatContext, filepath, NULL, NULL); if (status == 0) { status = avformat_find_stream_info(formatContext, NULL); if (status >= 0) { for (int i = 0; i < formatContext->nb_streams; i ++) { if (formatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) { audioindex = i; break; } } if (audioindex > -1) { codecContext = formatContext->streams[audioindex]->codec; AVCodec* codec = avcodec_find_decoder(codecContext->codec_id); if (codec) { status = avcodec_open2(codecContext, codec, NULL); if (status == 0) { success = true; } } } } } if (success) { av_dump_format(formatContext, 0, filepath, false); av_log(NULL, AV_LOG_DEBUG, "format and decoder sucessful, and now in decoding each frame\n"); printf("sample_rate=%d, channels=%d\n", codecContext->sample_rate, codecContext->channels); } avformat_free_context(formatContext);}int main(int argc, const char *argv[]){ const char filepath[] = "test2.mp3"; dump_file_format(filepath); return 0;}
好了,总结一下,本文介绍了在macos上,编译出iOS平台或Android平台的FFmpeg的链接库的过程,波及到编译环境的筹备、编译脚本的了解与定制等内容。有缘再见,see you.