ffmpeg入------安装
Fmpeg地址
FFmpeg源码地址:https://github.com/FFmpeg/FFmpeg
FFmpeg可执行文件地址:https://ffmpeg.org/download.html
Windows平台
Windows平台下载解压后如图所示(文件名称以-share结尾的是开发库)
FFmpeg库介绍
◆ ffmpeg.exe:用于音视频转码, 也可以从url/现场音频/视频源抓取输入源。
◆ ffplay.exe:一个非常简单和可移植的媒体播放器,使用FFmpeg库和SDL库。
◆ ffprobe.exe:查看多媒体文件的信息
将FFmpeg可执行文件加入系统环境变量,如下图所示:
Linux
ffmpeg官方 GitHub - FFmpeg/FFmpeg: Mirror of https://git.ffmpeg.org/ffmpeg.git
下载压缩包 或者 直接clone
- 直接clone:git clone https://github.com/FFmpeg/FFmpeg.git![](https://file.jishuzhan.net/article/1781211365344546818/2f5876dd7b5bbdc73519b3a0100c85aa.webp)![](https://file.jishuzhan.net/article/1781211365344546818/b642ff01c30bc463711b56e5026ff786.webp)
- 下载完成,执行./configure
如果出现了错误 nasm/yasm not found or too old. Use --disable-x86asm for a crippled build.
。
这是因为 FFMPEG为了提高编译速度,使用了汇编指令,如MMX和SSE等。如果系统中没有yasm
指令的话,就会该错误。
1)下载:wget http://www.tortall.net/projects/yasm/releases/yasm-1.3.0.tar.gz
2)解压:tar zxvf yasm-1.3.0.tar.gz
3)切换路径: cd yasm-1.3.0
4)执行配置: ./configure
5)编译:make
6)安装:make install
3.make && sudo make install
测试代码:
cpp
#include<stdio.h>
#include<libavutil/log.h>
int main()
{
av_log_set_level(AV_LOG_DEBUG); //设置日志等级
av_log(NULL, AV_LOG_INFO, "Hello~~~\n"); // INFO等级,输出hello
return 0;
}
编译链接: gcc -o ff_log ff_log.c -lavutil
或者 gcc -o ff_log ff_log.c `pkg-config --cflags --libs libavutil`
("pk g-config 工具:1)会检查库的版本号。如果所需要的库的版本不满足要求,它会打印出错误信息,避免链接错误版本的库文件;2)会获得编译预处理参数,如宏定义,头文件的位置。3)还会获得链接参数,如库及依赖的其它库的位置,文件名及其它一些连接参数)
选项*--cflags** 它是用来指定程序在编译时所需要头文件所在的目录, 选项 --libs则是指定程序在链接时所需要的动态链接库的目录。*
ffmpeg------log日志系统
log日志位于libavutil模块,log level的声明位于log.h
日志级别:
cpp
// 静默模式,不打印日志
#define AV_LOG_QUIET -8
// 立即崩溃,退出程序
#define AV_LOG_PANIC 0
// 严重出错,无法修复
#define AV_LOG_FATAL 8
// 程序出错
#define AV_LOG_ERROR 16
// 警告
#define AV_LOG_WARNING 24
// 信息
#define AV_LOG_INFO 32
// 详细信息
#define AV_LOG_VERBOSE 40
// 调试日志
#define AV_LOG_DEBUG 48
// 跟踪日志
#define AV_LOG_TRACE 56
设置日志等级的方法set_log_level()位于log.c,其中av_log_level是个静态全局变量,具体如下
cpp
static int av_log_level = AV_LOG_INFO;
void av_log_set_level(int level)
{
av_log_level = level;
}
常用的打印日志方法av_log(),声明位于log.h:
cpp
/**
* 发送特定消息到小于等于当前等级的日志,默认全部发送到stderr
*
* @param avcl 指向任意结构体的指针,结构体第一个变量为AVClass或NULL
* @param level 日志等级
* @param fmt 字符串格式
*/
void av_log(void *avcl, int level, const char *fmt, ...) av_printf_format(3, 4);
ffmpeg------文件的删除与重命名
- avpriv_io_delete() //删除
- avpriv_io_move() //重命名
编译链接: gcc xxx.c -o xxx -lavformat -lavutil
cpp
#include <libavformat/avformat.h>
int main(int argc,char *argv[])
{
int ret;
set_av_log_level(AV_LOG_DEBUG);
ret = avpriv_io_move("111.txt","222.txt");
if(ret < 0)
{
av_log(NULL,AV_LOG_ERROR,"Failed to move file:%s\n","111.txt");
return -1;
}
ret = avpriv_io_delete("./mytestfile.txt");
if(ret < 0)
{
av_log(NULL,AV_LOG_ERROR,"Failed to delete file:%s\n","mytestfile.txt");
return -1;
}
av_log(NULL,AV_LOG_DEBUG,"Success to delete file:%s\n","mytestfile.txt");
return 0;
}
ffmpeg------目录操作
重要结构体:
AVIODirContext 操作目录的上下文(记录avio_open_dir打开目录信息)
AVIODirEntry 目录项。用于存放文件名,文件大小等信息
操作目录API:
- avio_open_dir()
- avio_read_dir()//读取目录中每一个文件的属性
- avio_close_dir()
编译链接: gcc xxx.c -o xxx -lavformat -lavutil
cpp
// 实现简单的ls命令
#include <libavutil/log.h>
#include <libavformat/avformat.h>
int main(int argc,char* argv[])
{
int ret;
AVIODirContext *ctx = NULL;
AVIODirEntry *entry = NULL;
av_log_set_level(AV_LOG_INFO);
ret = avio_open_dir(&ctx,"./",NULL);
if(ret < 0){
av_log(NULL,AV_LOG_ERROR,"Cant open dir:%s\n",av_err2str(ret));
return -1;
}
while(1){
ret = avio_read_dir(ctx,&entry);//malloc entry
if(ret < 0){
av_log(NULL,AV_LOG_ERROR,"Cant read dir:%s\n",av_err2str(ret));
avio_close_dir(&ctx);
return -1;
}
if(!entry){
//the end
break;
}
av_log(NULL,AV_LOG_INFO,"%12"PRId64" %s\n",
entry->size,
entry->name);
avio_free_directory_entry(&entry);//free entry
}
avio_close_dir(&ctx);
return 0;
}
ffmpeg------重要的结构体
- AVIOContext(I/O上下文) // 实现文件或者流的I/O操作
- AVFormatContext(封装格式上下文) // 管理媒体文件的格式和封装信息
- AVCodecContext(编解码器上下文) // 控制和配置音视频编解码器的行为
- AVStream(音视频流) // 描述音视频流的属性
- AVPacket (数据包) // 用于在媒体文件、流之间传递数据
- AVFrame(帧) // 存储和传递音视频数据
- AVDictionary(字典) // 存储配置选项和元数据
- AVFilterContext(滤镜上下文) // 处理音视频数据,应用滤镜效果。
- SwsContext(图像转换上下文) // 进行图像处理和转换
- SwrContext(音频重采样上下文) // 进行音频处理和转换
AVIOContext结构体,用于管理媒体文件或者网络流的输入和输出操作
AVCodecContext结构体,包含了音频和视频编解码器的配置信息,如编码参数、解码参数、码率控制等。部分字段说明:
|---------------|----------------------------------------------|
| codec | 编解码器的AVCodec,比如指向AVCodec ff_aac_latm_decoder |
| width, height | 图像的宽高(只针对视频) |
| pix_fmt | 像素格式(只针对视频) |
| sample_rate | 采样率(只针对音频) |
| channels | 声道数(只针对音频) |
| sample_fmt | 采样格式(只针对音频 |
AVFormatContext结构体,是与多媒体文件格式相关的结构体,用于打开、读取和写入媒体文件。它包含了文件的格式信息、音视频流、文件I/O操作等。部分字段说明:
|--------------------------------|---------------------------------------------------------------|
| struct AVInputFormat* iformat | 输入媒体的AVInputFormat(输入数据的封装格式),比如指向AVInputFormatff_flv_demuxer |
| AVIOContext *pb | 输入数据的缓存 |
| unsigned int nb_streams; | 输出数据封装格式 |
| unsigned int nb_streams | 输入媒体的AVStream 个数 |
| AVStream** streams | 输入媒体的AVStream []数组 |
| int64_t duration | 输入媒体的时长(以微秒为单位),计算方式可以参考av_dump_format()函数 |
| int bit_rate | 输入媒体的码率 |
AVStream结构体,代表了音频或视频流,包括编解码参数、时间基准、时间戳等信息。部分字段说明
|----------------|--------------------------------|
| index | 标识该视频/音频流 |
| time_base | 该流的时基, PTS*time_base=真正的时间(秒) |
| avg_frame_rate | 该流的帧率 |
| duration | 该视频/音频流长度 |
| codecpar | 编解码器参数属性 |
AVPacket结构体,用于存储音频或视频数据包,包括编码后的数据和时间戳。部分字段说明:
|--------------|-------------|
| pts | 显示时间戳 |
| dts | 解码时间戳 |
| data | 压缩编码数据 |
| size | 压缩编码数据大小 |
| pos | 数据的偏移地址 |
| stream_index | 所属的AVStream |
AVFrame结构体,用于存储音频或视频帧的数据。它包括像素数据、采样数据、时间戳等。部分字段说明:
|---------------|---------------------------------|
| data | 解码后的图像像素数据(音频采样数据) |
| linesize | 对视频来说是图像中一行像素的大小;对音频来说是整个音频帧的大小 |
| width, height | 图像的宽高(只针对视频) |
| key_frame | 是否为关键帧(只针对视频) |
| pict_type | 帧类型(只针对视频) 。例如I, P, B |
| sample_rate | 音频采样率(只针对音频) |
| nb_samples | 音频每通道采样数(只针对音频) |
| pts | 显示时间戳 |
AVDictionary结构体,用于存储键值对,通常用于配置选项的传递和存储。
SwrContext结构体,用于音频重采样,支持不同采样率、通道数之间的转换
SwsContext结构体,用于图像转换,支持不同的像素格式和大小之间的转换
AVFilterContext结构体,用于配置和管理滤镜,包括音频滤镜和视频滤镜。
ffmpeg------多媒体文件
多媒体文件是一个容器(也可以理解为包装盒,常见的mp4、flv、mkv都是不同的包装盒 ),可以存放很多数据,最常见的有字幕数据、视频数据、音频数据。
在容器中有很多流(Stream/Track),流媒体文件中不同的流之数据不会相交的,比如音频流和视频流就是各自独立的。
**每种流是由不同的编码器编码的,**每条流数据在多媒体文件中是经过压缩的,但是其使用压缩的编码器都是不一样的。比如音频有可能是MP3,有可能是AAC,视频常见的压缩器有可能是H264或者H265。
从流中读出的数据称为包,在一个包中包含着一个或者多个帧。
ffmpeg操作流数据的基本步骤:
API:
打开读取输入流报头:
cpp
/* 打开一个输入流并读取报头。编解码器没有打开。流必须用avformat_close_input()关闭。
参数:
@param ps指向用户提供的AVFormatContext(由avformat_alloc_context)。可能是指向NULL的指针,在这种情况下,AVFormatContext由this分配函数并写入ps。注意,用户提供的AVFormatContext将被释放失败。
@param url打开的流的url。
@param fmt如果非null,该参数强制使用特定的输入格式。否则格式自动检测。
@param options一个由AVFormatContext和demuxer-private填充的字典选项。返回时,此参数将被销毁并替换为包含未找到的选项的字典。可能为NULL。
成功时返回0,失败时返回负AVERROR。
*/
int avformat open input(AVFormatContext *ps,
const char *url,
const AVinputFormat *fmt,
AVDictionary **options)
cpp
/*
在文件中找到"最佳"流。最佳流是根据各种启发式确定的,因为最可能是用户期望的。如果decoder参数非null, av_find_best_stream将为流的编解码器找到默认的解码器;找不到解码器的流将被忽略。
参数:
* @param ic 媒体文件句柄
* @param type 视频,音频,字幕等
* @param wanted_stream_nb 用户请求的流编号或-1为自动选择
* @param related_stream 尝试找到一个流相关(例如:在同一个程序中)到这个,如果没有,则为-1
* @param decoder_ret 如果非null,返回所选流的解码器
* @param flags 当前没有定义
@return
如果成功,返回非负的流号,如果没有找到请求类型的流,返回AVERROR_STREAM_NOT_FOUND,如果找到流但没有解码器,返回AVERROR_DECODER_NOT_FOUND
@note
如果av_find_best_stream返回成功并且decoder_ret不是NULL,那么*decoder_ret保证被设置为有效的AVCodec。
*/
int av_find_best_stream(AVFormatContext *ic,
enum AVMediaType type,
int wanted_stream_nb,
int related_stream,
const AVCodec **decoder_ret,
int flags);
cpp
//分配一个AVFormatContext。
// avformat_free_context()可以用来释放上下文和框架在其中分配的所有内容。
AVFormatContext *avformat_alloc_context(void);
cpp
/*返回与所提供参数最匹配的已注册输出格式列表中的输出格式,如果没有匹配则返回NULL。
@param short_name if non-NULL检查short_name是否与注册格式的名称匹配
@param filename if non-NULL检查filename是否以注册格式的扩展名结束
@param mime_type if non-NULL检查mime_type是否与注册格式的MIME类型匹配
*/
const AVOutputFormat *av_guess_format(const char *short_name,
const char *filename,
const char *mime_type);
cpp
/*向媒体文件添加新的流。
在解模时,由read_header()中的解模器调用。如果标志AVFMTCTX_NOHEADER在s.ctx_flags中设置,那么它也可以在read_packet()中被调用
当复用时,应该在avformat_write_header()之前由用户调用。
用户需要调用avformat_free_context()来清理分配,由avformat_new_stream()。
参数:
@param s 媒体文件句柄
@param c 未使用,不做任何事情
@return 新创建的流,错误时返回NULL。
*/
AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c);