image.png
默认的编译会生成4
个可执行文件和8
个静态库。可执行文件包括用于转码
、推流
、Dump媒体文件的ffmpeg
、用于播放媒体文件的ffplay
、
用于获取媒体文件信息的ffprobe
,以及作为简单流媒体服务器的ffserver
。
8个静态库其实就是FFmpeg的8个模块,具体包括如下内容。
AVUtil
核心工具库,该模块是最基础
的模块之一,下面的许多undefined其他模块都会依赖该库做一些基本的音视频处理操作。AVFormat
文件格式和协议库,该模块是最重要的模块之一,封 装了Protocol层和Demuxer、Muxer层,使得协议和格式对于开发者来说是透明的。AVCodec
编解码库,该模块也是最重要的模块之一,封装了 Codec层,但是有一些Codec是具备自己的License的,FFmpeg是不会默认添加像libx264、FDK-AAC、lame等库的,但是FFmpeg就像一个平台 一样,可以将其他的第三方的Codec以插件的方式添加进来,然后为开 发者提供统一的接口。AVFilter
音视频滤镜库,该模块提供了包括音频特效和视频特效的处理,在使用FFmpeg的API进行编解码的过程中,直接使用该模块为音视频数据做特效处理是非常方便同时也非常高效的一种方式。AVDevice
输入输出设备库,比如,需要编译出播放声音或者视频的工具ffplay
,就需要确保该模块是打开的,同时也需要libSDL的预先编译,因为该设备模块播放声音与播放视频使用的都是libSDL库。SwrRessample
该模块可用于音频重采样
,可以对数字音频进行声道数、数据格式、采样率等多种基本信息的转换。SWScale
该模块是将图像进行格式转换
的模块,比如,可以将 YUV的数据转换为RGB的数据。PostProc
该模块可用于进行后期处理,当我们使用AVFilter的时候需要打开该模块的开关,因为Filter中会使用到该模块的一些基础函数。比如AAC编码,常见的有两种封装格式
AAC
的bit stream filter
常常应用在编码
的过程中。
与音频的AAC编码格式相对应的是视频中的H264编码
,它也有两种封装格式
FFmpeg中也提供了对应的`bit stream
filter,称
H264_mp4toannexb`,可以将MP4封装格式的H264数据包转换为annexb封装格式的H264数据
(其实就是裸的H264的数据)包。
H264
的bit stream filter
常常应用于视频解码过程中。
ffmpeg
是进行媒体文件转码的命令行工具
ffprobe
是用于查看媒体 文件头信息的工具
ffplay
则是用于播放媒体文件的工具
1.首先用ffprobe查看一个音频的文件
ffprobe ~/Desktop/32037.mp3
2.输出格式信息format_name、时间长度duration、文件 大小size、比特率bit_rate、流的数目nb_streams等。
ffprobe -show_format 32037.mp4
3.以JSON格式的形式输出具体每一个流最详细
的信息
ffprobe -print_format json -show_streams 32037.mp4
4.显示帧信息的命令如下:
ffprobe -show_frames sample.mp4
5.查看包信息的命令如下:
ffprobe -show_packets sample.mp4
ffplay是以FFmpeg框架为基础,外加渲染音视频 的库libSDL来构建的媒体文件播放器。
业界内开源的ijkPlayer
其实就是基于ffplay
进行改造的播放器,当然其做了硬件解码以及很多兼容性的工作。
在 ffplay中音画同步的实现方式其实有三种。分别是
音频
为主时间轴 作为同步源视频
为主时间轴作为同步源外部时钟
为主时间轴作为同步源并且在ffplay
中默认的对齐方式也是以音频
为基准进行对齐的。
首先要声明的是,播放器接收到的视频帧或者音频帧,内部都会有时间戳(PTS时钟)
来标识它实际应该在什么时刻进行展示。
实际的对齐策略如下:比较视频当前的播放时间和音频当前的播放时间
过快
,则通过加大延迟或者重复播放来降低视频播放速度;放慢
了,则通过减小延迟或者丢帧来追赶音频播放的时间点。关键就在于音视频时间的比较以及延迟的计算,当然在比较的过程中会设 置一个阈值(Threshold)
,若超过预设的阈值就应该做调整(丢帧渲染
或者重复渲染),这就是整个对齐策略。
ffmpeg
就是强大的媒体文件转换工具。它可以转换任何格式的媒体文件,并且还可以用自己的AudioFilter
以及VideoFilter
进行处理和编辑。
ffmpeg -i output.mp4 -an -vcodec copy -bsf:v h264_mp4toannexb output.h264
ffmpeg -i test.aac -i test.h264 -acodec copy -bsf:a aac_adtstoasc -vcodec copy -f mp4 output.mp4
ffmpeg -i input.wav -acodec pcm_s16le -f s16le output.pcm
ffmpeg -i vocal.wav -i accompany.wav -filter_complex
amix=inputs=2:duration=shortest output.wav
ffmpeg -i input.mp4 -i changba_icon.png -filter_complex
'[0:v][1:v]overlay=main_w-overlay_w-10:10:1[out]' -map '[out]' output.mp4
ffmpeg -f rawvideo -pix_fmt yuv420p -s 480*480 -i texture.yuv -f image2-vcodec mjpeg output.jpg
容器/文件(Conainer/File)
即特定格式的多媒体文件,比如MP4
、flv
、mov
等。媒体流(Stream)
表示时间轴上的一段连续数据,如一段声音数 据、一段视频数据或一段字幕数据,可以是压缩的,也可以是非压缩的,压缩的数据需要关联特定的编解码器
。数据帧/数据包(Frame/Packet)
通常,一个媒体流是由大量的数据帧组成的,对于压缩数据,帧
对应着编解码器
的最小处理单元,分属于不同媒体流的数据帧交错存储于容器之中。编解码器
编解码器是以帧
为单位实现压缩数据
和原始数据
之间的相互转换的。AVFormatContext
就是对容器或者说媒体文件层次的一个抽象。AVStream
对流的抽象AVCodecContext
与AVCodec
对编解码格式以及编解码器的抽象AVPacket
与AVFrame
对于编码器或者解码器的输入输出部分,也就是压缩数据以及原始数据的抽象。AVFilter
对于音视频的处理肯定是针对于原始数据的处理,也就是针对于AVFrame
的处理。接下来介绍一个解码的实例,该实例实现的功能非常单一,就是把一个视频文件解码成单独的音频PCM文件和视频YUV文件。
avformat_network_init();
av_register_all();
压缩数据
),然后将压缩数据作为解码器
的输入,解码器将其解码为原始数据
(裸数据
),之后就可以将原始数据写入文件了。PCM
数据,视频就是YUV
数据image.png
AVFormatContext是API层直接接触到的结构体,它会进行格式的封 装与解封装。
image.png
该结构体包含的就是与实际的编解码
有关的部分。
3.3.1 av_register_all
所以该函数的内部实现会先调用avcodec_register_all
来注册所有config.h里面开放的编解码器,然后会注册所有的Muxer
和Demuxer
(也就是封装格式),最后注册所有的Protocol
(即协议层的东西)。
3.3.2 av_find_codec
这里面其实包含了两部分的内容:一部分是寻找解码器
,一部分是寻找编码器
。
3.3.3 avcodec_open2
该函数是打开编解码器(Codec)的函数,无论是编码过程还是解码过程,都会用到该函数。
avformat_open_input
根据所提供的文件路径判断文件的格 式,其实就是通过这一步来决定使用的到底是哪一个Demuxer
。
avformat_find_stream_info
该方法的作用就是把所有Stream
的MetaData
信息填充好。
av_read_frame
使用该方法读取出来的数据是AVPacket
。
对于音频流
,一个AVPacket
可能包含多
个AVFrame
,但是对于视频流
,一个AVPacket
只包含一
个AVFrame
,该函数最终只会返回一个AVPacket
结构体。
avcodec_decode
该方法包含了两部分内容:一部分是解码视频
,一部分是解码音频
,解码
是会委托给对应的解码器来实施的。
avformat_close_input
该函数负责释放对应的资源。
avformat_alloc_output_context2
该函数内部需要调用方法avformat_alloc_context来分配一个 AVFormatContext
结构体。
avio_open2
编码的阶段了,开发者需要将手动封装好的AVFrame
结构体,作为avcodec_encode_video
方法的输入,将其编码成为AVPacket
,然后调用av_write_frame
方法输出到媒体文件中。
本文参考音视频开发进阶指南
[项目源码地址 -
FFmpegDecoder](https://links.jianshu.com/go?to=https%3A%2F%2Fgithub.com%2Fzhanxiaokai%2FiOS-
FFmpegDecoder)
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。