FFMPEG 零基础编译过程

来源:互联网 发布:java int转char数组 编辑:程序博客网 时间:2024/05/30 02:53
最近做AAC编解码用到FFMPEG里面的库,看了不少雷大神的文章 http://blog.csdn.net/leixiaohua1020/article/category/1360795

这里写一个在看雷大神文章前我们需要如何下载和编译ffmpeg的文章,看到不少人也有写,这里这篇文章一方面记录我的项目过程,一方面做一个分享吧

文章步骤按正常开始ffmpeg下载代码到最后生成执行文件开始


现在时间是2017.08.02

开发环境: ubantu 12.04  (下面的步骤我基本都是linux下,window 的VS下的编译过程就暂时不写了,雷大神的博客都有)


本来是想从FFMPEG中只扣出来AAC用的代码和函数进行编译成库,后来发现FFMPEG函数之间的关联太多,结果引入一个文件后又产生新的编译错误!所以干脆全部编译,正好雷大神博客有说lib库,staic库,share库,开始我还看不懂是什么意思,看到别人写的FFMPEG之后才知道这些是通过上面下载的包编译出来的,下面是别人写的步骤

0. 配置(记录我敲过的命令,都是可以正常运行的命令,按下面顺序安装,如果不能运行,请另行百度)

0.1  在Ubuntu下安装SDL(编译ffplay需要),只需要依次执行下列命令:

sudo apt-get install libsdl1.2-dev
sudo apt-get install libsdl-image1.2-dev
sudo apt-get install libsdl-mixer1.2-dev
sudo apt-get install libsdl-ttf2.0-dev
sudo apt-get install gfx1.2-dev

0.2  安装Yasm:x264需要使用yasm来针对CPU架构进行优化,提高性能。
wget http://www.tortall.NET/projects/yasm/releases/yasm-1.2.0.tar.gz
tar xzvf yasm-1.2.0.tar.gz
cd yasm-1.2.0
./configure --prefix=/usr --enable-shared
make
make install


0.3  安装x264库(可以官网下载也可以git下载,我用的git) ,linux安装软件就是一层又一层的坑

sudo apt-get update

sudo apt-get installgit

git clone git://git.videolan.org/x264

cd x264

//动态库

./configure --enable-shared   
make
make install




1、下载ffmpeg。

FFMPEG下载地址:  http://www.ffmpeg.org/download.html#build-linux

下载ffmpeg-3.3.tar.xz,解压后里面有所有的ffmpeg文件

AAC相关官方说明: https://trac.ffmpeg.org/wiki/Encode/AAC


2、解压缩
tar -zxvf ffmpeg-2.0.1.tar.gz

2017.08.02增加一步:  将code拷贝到linux本身的文件系统目录下

考虑到很多人用的是虚拟机环境,有时候喜欢直接在window和Ubantu之间的共享文件夹里面进行编译程序,我在编译时又出现一下错误,查找别人说是要将code拷贝到linux本身的文件系统目录下才可以

root@virtual-machine:/mnt/hgfs/ubantu_share/ffmpeg-3.3# make
ln: failed to create symbolic link `libavutil.so': Operation not supported
make: *** [libavutil/libavutil.so] Error 1

解决办法:将code拷贝到linux本身的文件系统目录下才可以



3、配置,生成Makefile(用Ubantu自带的编译器是可以的)

./configure --enable-shared --disable-yasm --prefix=/usr/local/ffmpeg

因为最新的ffmpeg内置的aac 编码库不支持AV_SAMPLE_FMT_S16 这种格式,必须集成第三方的aac编码库,比如libfaac和libfdk-aac这两个库都可以,我是采用的libfdk-aac这个库,只要在编译ffmpeg 时加上如下开关

--enable-encoder=libfdk_aac为打开libfdk-aac 库,--enable-decoder=libfdk_aac和--enable-libfdk-aac设置aac 的编码和解码库为libfdk-aac 编码库,这样就会替换内部的默认aac编码库。

./configure --enable-shared --disable-yasm --enable-encoder=libfdk_aac --enable-decoder=libfdk_aac --enable-libfdk-aac --prefix=/usr/local/ffmpeg




如果执行结果不对,可以根据提示信息,并查看帮助,解决问题

./configure --help

4、编译安装

注意: 在make前,一定要用su切换root权限

make
make install

5、安装之后在/usr/local/ffmpeg会看到有三个目录
bin 执行文件目录
lib 静态,动态链接库目录
include 编程用到的头文件


通过以上5个步骤后我们就得到的FFMPEG的库文件和头文件,下面就可以开始编译了

编译之前,还需要执行以下一步

需要在/etc/ld.so.conf下面加一行/usr/local/ffmpeg/lib,保存过后ldconfig一下


FFMPEG编译后成库文件后-gcc编译我们的自己的写的文件时出现

ated-declarations]
main.cpp:146:43: warning: ignoring return value of ‘int avformat_write_header(AVFormatContext*, AVDictionary**)’, declared with attribute warn_unused_result [-Wunused-result]
/usr/bin/ld: warning: libswresample.so.2, needed by /usr/local/ffmpeg/lib/libavcodec.so, not found (try using -rpath or -rpath-link)
/usr/local/ffmpeg/lib/libavcodec.so: undefined reference to `swr_free@LIBSWRESAMPLE_2'
/usr/local/ffmpeg/lib/libavcodec.so: undefined reference to `swr_init@LIBSWRESAMPLE_2'
/usr/local/ffmpeg/lib/libavcodec.so: undefined reference to `swr_close@LIBSWRESAMPLE_2'
/usr/local/ffmpeg/lib/libavcodec.so: undefined reference to `swr_convert@LIBSWRESAMPLE_2'
/usr/local/ffmpeg/lib/libavcodec.so: undefined reference to `swr_is_initialized@LIBSWRESAMPLE_2'
/usr/local/ffmpeg/lib/libavcodec.so: undefined reference to `swr_alloc@LIBSWRESAMPLE_2'
collect2: ld returned 1 exit status

解决办法:

需要在/etc/ld.so.conf下面加一行/usr/local/ffmpeg/lib,保存过后ldconfig一下


编译雷大神写的simplest_ffmpeg_audio_encoder.cpp文件(我下面改成了main.cpp文件)就可以得到pcm->aac的编码程序.

编译命令:

gcc main.cpp -g -o main.out -I /usr/local/ffmpeg/include -L /usr/local/ffmpeg/lib -lavformat -lavcodec -lavutil



执行文件:./main.out出现以下错误

Output #0, adts, to 'tdjm.aac':    Stream #0:0: Unknown: none[aac @ 0x8d02d00] Specified sample format s16 is invalid or not supportedFailed to open encoder!
原因及解决办法:

http://bbs.csdn.net/topics/390700255?page=1

整形Sample的取值范围就是该整数类型的理论取值范围,比如AV_SAMPLE_FMT_U8的取值范围是从0到255,AV_SAMPLE_FMT_S16的取值范围是从-32768到32767.而浮点数有点不太一样,取值范围从-1.0到1.0。 数据类型越大,表示可以用于表示声音的范围越大,听起来也就越“高大上”

AVCodecContext有这几个成员request_channel(过时), request_channel_layout, request_sample_fmt. 通过在解码之前设定这几个成员,libav允许你指定解码后的Sample数据类型。

如果你真这么测试的话,你会发现解码后的Sample类型可能与你指定的不一致。这是因为,每个编码解码器都有支持的类型,比如说AAC编码只支持AV_SAMPLE_FMT_FLTP(在以前的版本上为AV_SAMPLE_FMT_S16),所以你需要在编码解码器支持的类型之上进行指定。

那么怎么才能知道某个编码解码器支持哪些音频采样格式(或者图像格式)呢,还暂时不是很清楚。不过应该有某种机制可以知道。

注意到AVSampleFormat里面还有几种格式以P(Planar,平面)结尾,那它们与不带P的有什么区别呢?当有多个Channel的时候,就有区别了。不带P的只有一个buffer,buffer里面Sample的分布是像这样A1B1A2B2A3B3......其中大写字母代表一个Channel,数字代表每个采样在该Channel里的编号。可以看出所有采样被放到一起(即一个buffer),不同的Channel被均匀的分布在其中。而带P的是像这样A1A2A3......B1B2B3......不同Channel各占一个buffer,且每个buffer长度一样。

音频解码之后,需要发送到第三方的音频输出库进行播放。可是这些播放库不一定支持libav的所有格式,前面说过AAC编码只会输出float planar类型的采样,那要怎样在不支持float planar的音频输出设备(比如Windows的WaveOut)上输出呢?有两种方法(其实是一种,两种方法原理一样),一个是采用libav的resample API(我试了半天,程序老是会crash),另外一种就是自己根据上面说到的布局来手动解决了。