Ubuntu
Ubuntu 中安装比较简单,因为包管理器中收纳了,直接用 apt 安装即可
sudo apt install -y ffmpeg
如果安装时提示找不到对应的安装包试一下升级系统再重新安装
sudo apt-get update
CentOS
由于 ffmpeg 是没有收入 yum 的,所以需要编译安装,会麻烦点。
wget https://ffmpeg.org/releases/ffmpeg-4.2.2.tar.bz2 #下载源文件
tar -jxv -f ffmpeg-4.2.2.tar.bz2 #解压缩
cd ffmpeg-4.2.2/ #进入解压缩后的文件夹
./configure --enable-gpl --prefix=/usr/local/ffmpeg #适配系统并指定安装的目录
报错:FFmpeg yasm/nasm not found or too old.Use --disable-yasm for a crippledbuild 是需要安装额外的 yasm 汇编编译器
原因:yasm是汇编编译器,ffmpeg为了提高效率使用了汇编指令,如MMX和SSE等。所以系统中未安装yasm时,就会报上面错误。
解决:
wget http://www.tortall.net/projects/yasm/releases/yasm-1.3.0.tar.gz
tar xzvf yasm-1.3.0.tar.gz
cd yasm-1.3.0
./configure
make
sudo make install
安装 yasm 后重新编译安装
./configure --enable-gpl --prefix=/usr/local/ffmpeg
make && make install
–enable-gpl 参数是为了安装后可以使用滤镜功能,如果不需要可以不加。(是 --enable-gpl,两个中划线 )
等待片刻后 ffmpeg 就被安装到 /usr/local/ffmpeg 目录下了。
测试程序:
#include <stdio.h>
#define __STDC_CONSTANT_MACROS
#ifdef _WIN32
#include <Windows.h>
//Windows
extern "C"
{
#include "libavformat/avformat.h"
};
#else
//Linux...
#ifdef __cplusplus
extern "C"
{
#endif
#include <libavformat/avformat.h>
#ifdef __cplusplus
};
#endif
#endif
int main()
{
printf("%s\n", avcodec_configuration());
return 0;
}
编译: gcc main.c pkg-config --cflags --libs libavformat libavutil libavcodec
而cmakelist.txt怎么编写呢?
- 有些CMake作为项目构建工具时,有一些库并没有提供cmake文件,往往提供的是
pkg-config
的.pc
文件,虽然可以在cmake
中用include_directories
和link_directories
来手动指定查找目录,但是这样写并不能保证跨平台,甚至同一个库在不同Linux发行版中的位置也不一样,这个时候最好的解决方法就是能够在 cmake 中(优雅地)使用pkg-config提供的信息。
拿FFmpeg举例,这是一个纯C库,并且没有提供cmake配置文件,接下来我们要在 cmake 项目中使用 ffmpeg;
pkg-config --list-all | grep libav
libavformat libavformat - FFmpeg container format library
libavcodec libavcodec - FFmpeg codec library
libavfilter libavfilter - FFmpeg audio/video filtering library
libavdevice libavdevice - FFmpeg device handling library
libavresample libavresample - Libav audio resampling library
libavutil libavutil - FFmpeg utility library
接下来我们在 CMakeLists.txt 中的相关位置添加如下语句:
find_package(PkgConfig REQUIRED)
pkg_check_modules(ffmpeg REQUIRED IMPORTED_TARGET libavcodec libavformat libavutil)
target_link_libraries(${PROJECT_NAME} PRIVATE PkgConfig::ffmpeg)
/**
* 最简单的FFmpeg Helloworld程序
* Simplest FFmpeg HelloWorld
*
* 雷霄骅 Lei Xiaohua
* leixiaohua1020@126.com
* 中国传媒大学/数字电视技术
* Communication University of China / Digital TV Technology
* http://blog.csdn.net/leixiaohua1020
*
*
* 本程序是基于FFmpeg函数的最简单的程序。它可以打印出FFmpeg类库的下列信息:
* Protocol: FFmpeg类库支持的协议
* AVFormat: FFmpeg类库支持的封装格式
* AVCodec: FFmpeg类库支持的编解码器
* AVFilter: FFmpeg类库支持的滤镜
* Configure: FFmpeg类库的配置信息
*
* This is the simplest program based on FFmpeg API. It can show following
* informations about FFmpeg library:
* Protocol: Protocols supported by FFmpeg.
* AVFormat: Container format supported by FFmpeg.
* AVCodec: Encoder/Decoder supported by FFmpeg.
* AVFilter: Filters supported by FFmpeg.
* Configure: configure information of FFmpeg.
*
*/
#include <stdio.h>
#define __STDC_CONSTANT_MACROS
#ifdef _WIN32
//Windows
extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libavfilter/avfilter.h"
};
#else
//Linux...
#ifdef __cplusplus
extern "C"
{
#endif
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavfilter/avfilter.h>
#ifdef __cplusplus
};
#endif
#endif
//FIX
struct URLProtocol;
/**
* Protocol Support Information
*/
char * urlprotocolinfo(){
char *info=(char *)malloc(40000);
memset(info,0,40000);
av_register_all();
struct URLProtocol *pup = NULL;
//Input
struct URLProtocol **p_temp = &pup;
avio_enum_protocols((void **)p_temp, 0);
while ((*p_temp) != NULL){
sprintf(info, "%s[In ][%10s]\n", info, avio_enum_protocols((void **)p_temp, 0));
}
pup = NULL;
//Output
avio_enum_protocols((void **)p_temp, 1);
while ((*p_temp) != NULL){
sprintf(info, "%s[Out][%10s]\n", info, avio_enum_protocols((void **)p_temp, 1));
}
return info;
}
/**
* AVFormat Support Information
*/
char * avformatinfo(){
char *info=(char *)malloc(40000);
memset(info,0,40000);
av_register_all();
AVInputFormat *if_temp = av_iformat_next(NULL);
AVOutputFormat *of_temp = av_oformat_next(NULL);
//Input
while(if_temp!=NULL){
sprintf(info, "%s[In ] %10s\n", info, if_temp->name);
if_temp=if_temp->next;
}
//Output
while (of_temp != NULL){
sprintf(info, "%s[Out] %10s\n", info, of_temp->name);
of_temp = of_temp->next;
}
return info;
}
/**
* AVCodec Support Information
*/
char * avcodecinfo()
{
char *info=(char *)malloc(40000);
memset(info,0,40000);
av_register_all();
AVCodec *c_temp = av_codec_next(NULL);
while(c_temp!=NULL){
if (c_temp->decode!=NULL){
sprintf(info, "%s[Dec]", info);
}
else{
sprintf(info, "%s[Enc]", info);
}
switch (c_temp->type){
case AVMEDIA_TYPE_VIDEO:
sprintf(info, "%s[Video]", info);
break;
case AVMEDIA_TYPE_AUDIO:
sprintf(info, "%s[Audio]", info);
break;
default:
sprintf(info, "%s[Other]", info);
break;
}
sprintf(info, "%s %10s\n", info, c_temp->name);
c_temp=c_temp->next;
}
return info;
}
/**
* AVFilter Support Information
*/
char * avfilterinfo()
{
char *info=(char *)malloc(40000);
memset(info,0,40000);
avfilter_register_all();
AVFilter *f_temp = (AVFilter *)avfilter_next(NULL);
while (f_temp != NULL){
sprintf(info, "%s[%15s]\n", info, f_temp->name);
f_temp=f_temp->next;
}
return info;
}
/**
* Configuration Information
*/
char * configurationinfo()
{
char *info=(char *)malloc(40000);
memset(info,0,40000);
av_register_all();
sprintf(info, "%s\n", avcodec_configuration());
return info;
}
int main(int argc, char* argv[])
{
char *infostr=NULL;
infostr=configurationinfo();
printf("\n<<Configuration>>\n%s",infostr);
free(infostr);
infostr=urlprotocolinfo();
printf("\n<<URLProtocol>>\n%s",infostr);
free(infostr);
infostr=avformatinfo();
printf("\n<<AVFormat>>\n%s",infostr);
free(infostr);
infostr=avcodecinfo();
printf("\n<<AVCodec>>\n%s",infostr);
free(infostr);
infostr=avfilterinfo();
printf("\n<<AVFilter>>\n%s",infostr);
free(infostr);
return 0;
}