• 多媒体开发(7):编译Android与iOS平台的FFmpeg


    编译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文件:
    pc文件

    这样安装pkg-config:

    brew install pkg-config

    安装pkg-config后,可以这样获取第三方库的路径信息:

    pkg-config --cflags --libs freetype2

    以下是对于pkg-config命令的一个载图:
    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.git
    sudo 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.google.cn/ndk/downloads/index.html

    (2)FFmpeg源码下载

    git clone git://source.ffmpeg.org/ffmpeg.git ffmpeg

    (3)编译脚本

    不必自己重写了,找开源的项目过来修改一下(注意开源协议)就可以了,比如参考这个开源项目: https://github.com/yixia/FFmpeg-Vitamio.git

    在这个项目里面,有编译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
    ");
    		printf("sample_rate=%d, channels=%d
    ", 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.


    动动脑,不会老

  • 相关阅读:
    2016年第9本:系统之美
    2016年第8本:不可思议的心理控制实验
    2016年第7本:非暴力沟通
    用SDWebImage渐变加载图片
    iOS相册、相机、通讯录权限获取
    屏蔽iOS10模拟器海量的垃圾debug信息
    Swift
    Swift
    PlaceholderImageView
    Swift
  • 原文地址:https://www.cnblogs.com/freeself/p/14329913.html
Copyright © 2020-2023  润新知