ffmpeg播放器实现详解 - 音频同步控制
在深入剖析ffmpeg播放器实现的移植源码移植音频同步控制之前,让我们首先理解同步的移植源码移植时间基准。在ffmpeg的移植源码移植体系中,有三种时间基准:音频时钟、移植源码移植视频时钟与系统时钟。移植源码移植视频时钟用来追踪当前视频播放的移植源码移植源码实现域名授权时间戳位置,计算方式大致等于当前播放视频帧的移植源码移植pts加上一个修正值delta。这一修正值delta在取得视频时钟(即当前帧pts)的移植源码移植时刻与调用get_video_clock时刻之间的时间间隔上,用于修正延迟。移植源码移植系统时钟追踪的移植源码移植是系统时间戳,它以1/秒为单位,移植源码移植便于在不同平台间移植。移植源码移植值得注意的移植源码移植是,不同流媒体协议和媒体格式的移植源码移植时间戳格式各有不同,因此,移植源码移植ffmpeg以1/.0作为其内部时基基准。实现系统时钟的方式可参考相关注释。
在已经具备了音视频及系统时钟的基础之上,我们可以根据主同步源类型获取相应的时间戳值。接下来,让我们探讨音频同步策略。为了音频的同步,我们引入了几个关键变量以追踪音频时钟与主同步源间的时差,并控制同步时机。音频同步的原理与视频同步类似,通过增加或减少音频数据的播放时间来实现。与视频同步不同,音频帧播放时间较短,约为.ms。因此,音频同步采用插值或丢帧的方式来实现,避免因同步操作带来的声音失真变形。具体实现时,当音频时钟滞后于主时钟,采用插值方式,通过复制最后一个音频数据进行插值,iappq绑查询源码以实现与主时钟同步。而当音频时钟超前于主时钟,则直接采取丢帧方式,将超前主时钟时间对应的采样数据丢弃。
在音频同步的实现中,选择合适的同步时机至关重要。通常,视频播放速率保持在fps左右,音频帧播放时间则较短,约为.ms。由于音视频播放时间不相等,音频同步是相对的、暂时的,而非绝对同步。因此,我们需要选择恰当的时机对音频进行同步,避免过多的插值与丢帧操作,以确保声音波形的平滑度。这通常通过追踪音频不同步次数的变量来实现。当判定音频时钟与主同步源的时差超过某个阈值时,增加音频不同步的次数,直到达到某个阈值时触发丢帧或插值动作。同时,考虑到时差的波动性,采用加权方式评估时差的大小,以降低早期时差对总时差的影响。
在深入理解音频同步策略之后,让我们通过源码编译验证理论知识。源码的编译方法与之前的例程保持一致,可使用Makefile脚本进行编译。执行make命令即可开始编译过程,编译完成后,可在源码目录生成名为tutorial的可执行文件。使用方法类似于ffplay,执行tutorial url命令,360免费认证 源码其中url可为本地视频文件或媒体流地址。通过输入Ctrl+C即可结束程序运行。
零基础读懂视频播放器控制原理: ffplay 播放器源代码分析
视频播放器的核心原理在于控制音视频帧序列,其中ffplay作为FFmpeg自带的播放器,利用ffmpeg解码库和sdl库进行视频渲染。本文将通过分析ffplay源代码,深入解析音视频同步、播放控制的原理。
FFmpeg的跨平台特性使得在PC端分析代码更为高效,本文则主要聚焦于ffplay for MFC的移植代码。首先,理解视频文件结构,每个MP4文件包含封装格式、比特率等信息,音视频被区分为独立的stream,并有各自的参数。解复用后,音频和视频帧转化为原始数据,进入播放流程,如图2所示。
简化播放器,仅考虑视频解码和SDL显示,其流程图显示了FFmpeg初始化、读取并解码帧、然后渲染到窗口的过程。为了实现音视频同步,播放器需要处理帧率、音频采样率和视频帧显示时间的关系,以及不同流的帧数差异。
文章接下来提出五个关键问题,涉及画面、字幕和声音的组合,音视频同步的具体机制,以及快进/后退操作的实现。ffplay通过定义VideoState结构体,乐彩影视源码将播放控制分发到不同线程,利用PTS时间戳确保音视频同步。视频播放器操作的实现包括控制暂停和播放,以及通过时间而非帧数进行快进/后退,以保持同步。
分析ffplay代码时,整体结构包括定时器刷新、多线程解码和显示,以及关键控制函数的使用。在深入理解PTS和DTS后,我们看到ffplay如何动态调整PTS以实现音视频同步。最后,文章总结了通过ffplay源码学习到的基础概念和实用技巧,强调了从基础开始理解、代码架构分析和平台选择的重要性。
FFMPEG编译裁剪移植
1.ffmpeg文件结构说明
1.1 ffmpeg模块说明
libavformat
用于各种音视频封装格式的生成和解析,包括获取解码所需信息以生成解码上下文结构和读取音视频帧等功能;音视频的格式解析协议,为 libavcodec 分析码流提供独立的音频或视频码流源。
libavcodec
用于各种类型声音/图像编解码。该库是音视频编解码核心,实现了市面上可见的绝大部分解码器的功能。
libavdevice
硬件采集、加速、显示。操作计算机中常用的音视频捕获或输出设备。
libavfilter
音视频滤波器的开发,如宽高比、裁剪、格式化、非格式化伸缩。
libavutil
包含一些公共的工具函数的使用库,包括算数运算、字符操作。
libavresample
音视频封转编解码格式预设等。
libswscale
原始视频格式转换,bc源码站用于视频场景比例缩放、色彩映射转换;图像颜色空间或格式转换,如 rgb、rgb 等与 yuv 等之间转换。
libswresample
原始音频格式转码。
libpostproc
同步、时间计算的简单算法,用于后期效果处理;音视频应用的后处理,如图像的去块效应
在编译ffmpeg源码之前,我们可以通过配置编译参数选择是否编译生成如上库。一般而言,要实现最基本的音视频编解码功能,libavformat,libavcodec,libavutil这三个库是不可缺少的。我们通过使能或失能ffmpeg支持的组件,如编解码器、分流器、合流器、解析器、协议类型等,来裁剪库文件的大小。
1.2名词解释
encoder // 编码器
decoder // 解码器
hwaccel // 硬件加速器
muxer // 合流器
demuxer // 分流器
parser // 解析器
bsf // 比特过滤器
protocol // 协议
indev // 输入设备
outdev // 输出设备
filter // 过滤器
相关学习资料推荐,点击下方链接免费报名,先码住不迷路~
音视频免费学习地址:FFmpeg/WebRTC/RTMP/NDK/Android音视频流媒体高级开发
免费分享音视频学习资料包、大厂面试题、技术视频和学习路线图,资料包括(C/C++,Linux,FFmpeg webRTC rtmp hls rtsp ffplay srs 等等)有需要的可以点击 加群免费领取~
2.编译
ffmpeg 编译帮助
主要包含一下选项
Help options // 帮助选项,可以查看全部支持的编解码,硬件加速器,解析器、输入输出设备等参数的列表,一般做裁剪时需要查询;
Standard options // 标准选项,主要是目录路径相关的设置,常用的为--prefix=PREFIX 设置安装路径;
Licensing options // license 相关选项 GPL使能设置相关;
Configuration options // 配置选项,常用的--disable-static关闭静态库 默认是开启静态库编译的--enable-shared 使能动态库编译,编译出动态库--enable-small优化大小而不是注重运行速度;
Program options // 编译出工具文件,一般的bin文件,常用的ffmpeg ffprobe 和ffplay三个工具的bin文件编译;
Documentation options // 文档选项,是否构建文档页面,个人猜测是工具的帮助文件是否编译进去,里面支持html manpage txt等格式文件;
Component options // 组件选项,常用使能或者关闭某些模块的编译,libavformat,libavcodec,libavutil这三个库一般是不可或缺的,还有其他的组件按自己需要使能;
Individual component options // 独立的组件选项,更为具体的组件编译选项,如果需要剪裁一般情况先使用--disable-everything 关闭全部的组件,然后再单独开启需要的组件;
External library support // 扩展库支持,允许FFmpeg链接到相应的外部库;
Toolchain options // 工具链选项,交叉编译常用,比较常用的--arch=ARCH 指定系统架构 --cpu=CPU指定cpu类型 --cross-prefix交叉编译工具链前缀 --enable-cross-compile 使能交叉编译--target-os=OS指定操作系统;
Advanced options (experts only) // 高级选项,一般较少使用,不懂的请慎用,以免引进bug;
Optimization options (experts only): --disable-asm关闭所有的优化选项
Developer options (useful when working on FFmpeg itself): --disable-debug 关闭调试符号信息,减小库大小;
2.1全编配置
采用默认配置 交叉编译,在当前目录下output文件夹生成对应的文件
编译后的文件夹下有bin include lib share 目录bin存放交叉编译后的ffmpeg等工具bin文件,include目录存放头文件,移植需要 lib存放动态和静态库,将lib里面的文件拷贝到板端或者静态库使用即可;
编译后未经裁剪的ffmpeg库实在太大,十几M的大小,需要裁剪;
2.2裁剪库
ffmpeg 库过大,很多功能其实没必要使用的, 裁剪为仅支持mp4 和 avi两种格式的视频,avi:视频采用h编码,音频采用pcm_alaw mp4:视频h,音频aac格式;这个指令其实还可以进一步裁剪,不想麻烦,够用就行,不再裁剪@_@;
裁剪后的文件大小最大也只剩1.1M,大小减少倍;
3.ffmpeg移植问题
3.1时间冲突问题
libavutils/time.h文件名字和linux系统的time.h的名字冲突,在编译的时候会出现time.h文件是有两个,无法区分是哪个time.h,因此会出现报错,如果在ffmepg里将time.h文件重命名可以解决这个问题,但这样太麻烦而且容易出错,采用另外一种方式,将makefile的搜索路径更改为只搜索到include文件夹,然后在include文件夹下放置相关的头文件,而在调用的c文件上路径改为
这样就躲开了搜索文件名字一样的问题,其本质是将ffmpeg的time.h重新命名为libavutils/time.h
3.2函数符号导出问题
由于移植需要单独导出库内部的局部函数,如mov_write_packet mov_write_header mov_write_trailer等函数,将movenc.c对应函数的static去掉,同时在libavformat.h文件声明函数,但是生成的库会发现没有找到对应的函数符号
avi相关的函数也做同样的处理,但是avi有这个函数符号,这个问题只能反推编译过程查找哪里将函数符号屏蔽掉了采用指令
发现在生成库的时候会调用一个脚本文件,这个脚本文件最后在config.mak里面指定了
--version-script这个选项仅仅导出要使用的符号表,这个文件对应libavformat里面的就是libavformat.vlibavformat.verlibavformat.version,后两个文件都是根据第一个文件产生的,查看libavformat.v文件
显然,在这里屏蔽掉了非av开头的全部函数,所有mov开头的函数无法被外部调用,因此更改这个文件,将mov开头的函数也导出
重新编译发现可以调用mov开头的函数了。
不足之处,敬请指出,谢谢^_^
4.参考资料
CSDN 博客 SigmaStarDocs 《ffmpeg基础库编程开发》
原文 FFMPEG编译裁剪移植_ffmpeg编译到移远模块_Kingkim的博客-CSDN博客
FFmpeg学习(一)开篇
为什么要学习FFmpeg?本人希望深入研究音视频领域,音视频领域内容丰富,我计划从多个方面逐步学习:FFmpeg常用功能实践、FFmpeg源码研究、OpenGL、OpenGLES、Metal、AR、WebRTC、直播架构等。
当前音视频有哪些应用场景?从众多应用场景可以看出,音视频技术至关重要,尤其在5G时代,网络传输问题得到极大提升,音视频需求将爆发式增长。以下是一个简单播放器架构图:
音频解码和视频解码一般使用FFmpeg解码,iOS8之后提供了VideoToolBox框架支持硬解码。视频渲染通常使用OpenGL直接利用GPU渲染,还有GPUImage、SDL、VLC等第三方框架。
音视频播放中的音视频同步是一项复杂的技术。学习一项技术需要高效的方法,只有不断实践才能深刻理解。学习FFmpeg也需要好的文档,以下列举一些必备的学习文档地址:
以上都是英文文档,如果英文学习困难,可以参考以下中文资料:
此外,推荐两本非常好的书籍:
相关学习资料推荐,点击下方链接免费报名,先码住不迷路~
1. FFmpeg简介:FFmpeg是一套用于记录、转换数字音频、视频并将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常先进的音频/视频编解码库libavcodec,为了保证高可移植性和编解码质量,libavcodec里很多code都是从头开发的。FFmpeg在Linux平台下开发,但也可以在其他操作系统环境中编译运行,包括Windows、Mac OS X等。这个项目最早由Fabrice Bellard发起,年至年间由Michael Niedermayer主要负责维护。许多FFmpeg的开发人员都来自MPlayer项目,当前FFmpeg也是放在MPlayer项目组的服务器上。项目的名称来自MPEG视频编码标准,前面的"FF"代表"Fast Forward"。
2. FFmpeg能做什么
3. FFmpeg架构模块组成:我们先看一张FFmpeg的架构图:
下载好的源码,我们也可以看到大致的源码结构:
3.1 libavutil
3.2 libavformat
FFmpeg是否支持某种媒体封装格式,取决于编译时是否包含了该格式的封装库。根据实际需求,可进行媒体封装格式的扩展,增加自己定制的封装格式,即在AVFormat中增加自己的封装处理模块。
3.3 libavcodec
AVCodec中实现了目前多媒体绝大多数的编解码格式,既支持编码,也支持解码。AVCodec除了支持MPEG4、AAC、MJPEG等自带的媒体编解码格式之外,还支持第三方的编解码器,如H.(AVC)编码,需要使用x编码器;H.(HEVC)编码,需要使用x编码器;MP3(mp3lame)编码,需要使用libmp3lame编码器。如果希望增加自己的编码格式或硬件编解码,则需要在AVCodec中增加相应的编解码模块。
3.4 libavfilter
3.5 libavdevice
3.6 libswscale
3.7 libpostproc
3.8 libswrressample
3.9 ffmpeg
3. ffsever
3. ffplay
4. FFmpeg安装:下载源码后,我们可以查看一下目录结构:
输入./configure --help命令查看配置信息
内容太多需要分页,输入./configure --help | more
从上面的帮助,我们可以尝试输入:./configure --list-decoders查看所有解码器
接下来我们可以尝试输入:./configure --list-encoders查看所有编码器
接下来我们可以尝试输入:./configure --list-filters查看所有滤镜器
接下来我们可以尝试输入:./configure --list-muxers查看FFmpeg的封装,封装Muxing是指将压缩后的编码封装到一个容器格式中,我们输入./configure --list-muxers来查看FFmpeg支持哪些容器格式:
从上面打印信息来看,FFmpeg支持生成裸流文件,如H.、AAC、PCM,也支持一些常见的格式,如MP3、MP4、FLV、M3U8、WEBM等。
从上面解封装又称为解复用格式的支持信息中可以看到,FFmpeg支持的demuxter非常多,包含image、MP3、FLV、MP4、MOV、AVI等。
从支持的协议列表中可以看到,FFmpeg支持的流媒体协议比较多,包括MMS、HTTP、HTTPS、HLS、RTMP、RTP,甚至支持TCP、UDP,它还支持使用file协议的本地文件操作和使用concat协议支持的多个文件串流操作。
接下来我们可以尝试输入:./configure --list-parsers查看FFmpeg支持的解析器
接下来我们可以尝试输入:./configure --list-bsfs查看FFmpeg支持的字节流过滤器
接下来我们可以尝试输入:./configure --list-indevs查看有效的输入设备
接下来我们可以尝试输入:./configure --list-outdevs查看有效的输出设备
2024-12-24 08:46
2024-12-24 08:42
2024-12-24 08:32
2024-12-24 08:21
2024-12-24 06:47