1.C/C++开发人员要了解的网络几大著名C/C++开源库
2.怎么把YouTube视频下载到电脑上
3.VLC播放器
4.ffplay视频播放原理分析
C/C++开发人员要了解的几大著名C/C++开源库
在开源软件领域,众多知名的流播络流国产软件如暴风音影、腾讯会议、放器法PC版微信等,源码用方背后都依托于一些大型的多窗C/C++开源库。本文将深入介绍几种日常工作中常用的口网网吧软件源码C/C++开源库,为开发者提供借鉴与参考。媒体
**多媒体处理开源库FFmpeg
**FFmpeg,播放享有盛名的器使音视频多媒体处理开源库,几乎每个做过音视频编解码开发的网络开发者都熟悉。它包含了广泛而全面的流播络流音视频编码协议,如H、放器法H、源码用方MPEG4、多窗H等,口网并提供了一整套音视频处理解决方案。从音视频采集与编码、解码、格式转换到视频抓图和加水印,FFmpeg都能轻松应对。其强大的sdk接口允许开发者直接接收和发送码流,读写文件,进行编解码操作,以及修改解码数据格式等。
FFmpeg基于C语言实现,执行效率接近汇编语言,特别适合对实时性有高要求的音视频处理场景。项目中常包含优化效率的汇编代码,直接控制操作以达到最优性能,不依赖通用编译器生成的汇编代码。
几乎所有的视频播放器都依赖FFmpeg的音视频解码功能,包括暴风影音、QQ影音、腾讯视频、爱奇艺视频、优酷视频等。播放器通过将压缩的视频图像帧解码为并连续显示来实现动态播放效果。帧率达到帧时,人眼就能感知连续动态的播放。
FFmpeg支持多种音视频格式的相互转换,广泛应用于格式工厂、暴风转码、QQ音影视频格式转换工具、狸窝视频转换器、迅捷视频转换器等软件。
**实时音视频处理开源库WebRTC
**WebRTC,由Google发起的实时音视频通讯开源库,提供了从音视频采集、编码、网络传输到解码渲染的整套解决方案。WebRTC使得开发者能够轻松构建实时音视频应用,无需下载插件,只需编写简单的JavaScript程序即可实现。
WebRTC基于C/C++实现,具有跨平台性能,支持Windows、MAC、iOS和Android等多系统,通过调用相应系统的SDK即可构建音视频应用。虽然称为WebRTC,它不仅支持Web间通讯,还支持Windows、Android和iOS平台。
WebRTC因其出色的音视频效果和网络适应性,广泛应用于视频会议、实时音视频直播等领域。腾讯会议、华为WeLink、字节飞书、阿里钉钉、科达、ZOOM、小鱼易连等均采用了WebRTC方案提供视频会议服务。声网(Agora)基于开源WebRTC库,提供了多个行业的音视频互动解决方案,服务覆盖了包括小米、陌陌、斗鱼、哔哩哔哩、新东方、小红书、HTC VIVE、The Meet Group、Bunch、Yalla等企业和机构。
**Chromium浏览器内核开源库Chromium
**Chromium是Google的久负盛名的浏览器开源项目,作为Chrome浏览器的引擎,其设计理念强调简单、高速、稳定与安全。Chromium采用了WebKit渲染引擎和V8 JavaScript引擎,支持沙盒、黑名单、无痕浏览等功能,提供了稳定与安全的网页浏览环境。
Chromium与Chrome浏览器的关系:Chromium是Google的开源项目,而Chrome是基于Chromium维护的浏览器,添加了更多功能并进行了优化。Chromium面向的是极客、开发人员和体验新功能的用户。
Chromium的根目录下包含了多个文件夹,如Android WebView实现、dynainfo指标源码Chromium浏览器代码、base模块、breakpad崩溃报告、build构建配置、cc合成器实现等。Chromium使用多进程架构,支持多种协议的网络通信,提供丰富的API接口,适合开发者深入研究。
**Chromium嵌入式框架开源库CEF
**CEF,Chromium Embedded Framework,是一个基于Chromium的开源浏览器控件,使用C++实现。它作为浏览器控件嵌入到应用程序中,允许在应用窗口中打开网页。CEF提供了稳定且丰富的API接口,支持Windows、Linux、Mac等多个平台,能与Webkit渲染引擎和HTML5特性兼容。
CEF典型应用场景包括:嵌入浏览器控件到本地应用、创建轻量级浏览器壳、离线渲染Web内容、自动化Web测试等。许多C/S架构的PC桌面程序,如QQ、PC版微信、企业微信、钉钉、飞书、迅雷、爱奇艺视频客户端、优酷视频客户端、有道词典、有道云笔记、MindMaster等,都内嵌了CEF浏览器控件。
**多协议网络传输开源库libcurl
**libcurl是一个跨平台的网络传输库,支持多种协议如ftp、ftps、/download-youtube-video/。
我觉得非常好用。它的特点是什么?第一,支持多平台,MacOS、Linux、windows,甚至安卓都可以用。第二,没有广告,也很安全,这个工具我已经用了很多年了,非常安全。现在,我们就来介绍一下这个工具如何使用。
1. 首先,我们到它的网站:Freedownloadmanager.org
2. 我们点“Free Download”,就能下载这个工具了。再跟大家讲一下它支持哪些版本。默认情况下,因为我是windows系统,所以下载的是windows版本的程序,它还支持MacOS、安卓、Linux和谷歌Chrome浏览器以及火狐浏览器的插件。所以,你要感兴趣的话,你也可以下载插件版本的,用起来更方便。
3. 下载后进行安装,安装完之后,我们来看看到底怎么下载视频。打开一个YouTube的视频,点击右键,选择copy这个视频的地址:
4. 复制视频url地址的目的是用来放在Free Download Manager视频下载器中。打开下载器程序,点左上角的加号,然后它会自动把你刚才拷贝的视频地址给放进来,你只需要再点ok就可以了:
5. 下载工具开始分析这个视频,找出来它的各种格式,可以看到5.个g的p分辨率的都支持下载:
如果视频有字幕的话,这个工具也支持下载,上图中的选项里会有字幕下载项目。
方法2:在火狐浏览器中使用Easy YouTube Video Downloader Express插件
1. 首先,下载安装火狐浏览器。
2. 然后,用浏览器打开谷歌搜索“download youtube for firefox”,寻找火狐浏览器可以使用的YouTube下载器插件:
搜到一个插件叫做“Easy YouTube Video Downloader Express”,点击打开这个链接:
3. 在跳转到的插件页面中,可以把插件安装到火狐浏览器中,安装按钮和下图一致。插件添加后,显示如下:
4. 在油管中找到你想要下载的视频,就可以在视频下方看到这么一个下载的按钮,点一下,里面有各种下载选项,有p、p、p,你可以选择你要下载的高清度:
5. 直接点击,就可以开始下载了。gitkeep的源码
方法3:在电脑上使用DownSub下载视频字幕
DownSub是一个免费的web应用程序,可以直接从Youtube、VIU、Viki、Vlive等网站下载视频字幕。这款工具支持下载的字幕格式:SRT,TXT。
DownSub不会强迫用户下载或安装任何类型的扩展或第三方软件。它提供了一种在线下载视频字幕的方法,只需输入视频的URL并点击下载,操作步骤如下:
1. 首选,复制YouTube视频的url地址。你可以在视频上右键点击copy,也可以在视频下方的分享share中找到视频地址:
2. 然后,我们打开DownSub网站:Downsub.com,这是专门下载YouTube字幕的网站:
3. 我们把之前得到的Youtube视频链接粘贴到上图的框中,然后我们只需要点“DOWNLOAD”,下载工具就会自动分析这个视频中包含的字幕信息。分析好了后,它会提供两个下载版本:
一个是SRT版本,这就是标准的字幕文件;还有一个TXT文件版本,都可以下载。同时,这个工具可以侦测出Youtube视频字幕是哪种语言。如果,你想要把字幕翻译成其他语言,可以在第二语言中进行选择,就会生成对应的语言版本:
方法4:在电脑上使用Savieo
Savieo是一款线上的下载视频的工具,支持常见的YouTube等平台的视频下载,只需要把视频的网址粘贴进入,就可以在线下载视频,具体操作步骤:
1. 首先,打开Savieo的官网:Savieo.com:
在它的首页上,我们可以发现这款视频下载工具不仅仅支持油管的视频,还支持很多其他视频网站:
2. 把待下载视频的Url地址填入框中,然后点击DOWNLOAD按钮,这个工具会解析视频,给出几个不同清晰度的下载选项:
3. 选择你想要下载的版本,比如p的,点击对应清晰度后面的“DOWNLOAD”,会跳转到对应分辨率的视频界面,然后在视频右下角进行下载:
方法5:在电脑上使用Loader.to
这款工具可以用来下载各种格式的YouTube视频,最高可支持8K分辨率的视频下载。使用它的方法也很简单:
1. 首先打开其官网:Loader.to,然后填入你想要下载的视频地址,选择好格式,点击“DOWNLOAD”解析视频:
2. 视频会在下方进行解析,完成后即可下载:
方法6:在手机上使用YouTube Premium
如果您不住在这些国家/地区之一,下载视频需要订阅YouTube Premium。此订阅费用为个人每月.美元或同一家庭中最多5人每月 .美元,并包括订阅YouTube音乐等多种福利。
无论您是否需要高级订阅,过程都完全相同。虽然这是下载YouTube视频的最简单方法,但您将无法在应用程序之外访问视频;为此需要第三方工具的帮助。
购买YouTube Premium后,下载视频的方法:
1. 在手机上打开YouTube应用。
2. 打开您要下载的视频。
3. 点击视频下方的下载按钮。
4. 选择下载的视频质量。如果您尚未订阅YouTube Premium,该应用会在您下载视频之前提示您进行订阅,
/download-youtube-video/。
5. 点击下载。
下载后,“下载”按钮将变为黑色勾号并显示“已下载”。离线时可以在YouTube应用的主页选项卡中访问下载的视频。
您可以通过点击“Downloaded”按钮并点击删除来删除已下载的YouTube视频。
方法7:在手机上使用TubeMate
TubeMate是允许您下载YouTube视频的众多服务之一,使用方法如下:
1. 通过APKMirror下载TubeMate应用程序。
2. 打开YouTube应用。
3. 打开您要下载的视频。
4. 点击视频正下方的分享图标。
5. 点击应用列表上的TubeMate。
6. 允许TubeMate获取权限。
7. 选择下载的视频格式。
8. 点击红色的下载按钮。
9. 点击屏幕底部的向下箭头,以查看下载状态。
您可以通过两种方式访问下载的视频。打开TubeMate应用程序并点击屏幕底部的已下载按钮,或者您可以在手机存储中找到视频。它们将位于Google文件的内部存储 视频中。
方法8:在视频地址里加入“SS”
无需安装软件即可下载YouTube视频的第一个选项是通过SaveFromNet。SaveFromNet声称它提供了一种使用其“SS”来获取YouTube视频的简单、快捷的方法。借助此功能,您只需在YouTube链接中添加代码“SS”,即可使用这款基于网络的应用程序尽快获取视频。
同时,使用SaveFromNet,您可以将视频保存为MP4和WEBM格式。您还可以下载高质量YouTube视频,因为它提供高达p的分辨率。 此外,SaveFromNet还能够将油管视频转换为MP3格式。如果您想知道如何在不安装软件的情况下从YouTube下载视频,请依照以下步骤,
/download-youtube-video/。
1. 从网络浏览器访问YouTube的官方网站并选择一个您想要下载的视频。
2. 接下来,jps命令源码将鼠标悬停在页面最上方的URL栏中。然后,在youtube.com 之前输入“SS”,然后单击Enter键。
3. 之后,您将被自动重定向到YouTube视频下载页面。在此处,单击下载按钮旁边的下拉菜单。然后,从提供的格式(MP4、MP3 和 WEBM)中选择一种并等待片刻,直到您的文件成功下载。
方法9:在电脑上使用YouTubeMp4
YouTubeMp4是一个第三方网站可以让用户在几分钟内下载YouTube视频。您所要做的就是复制粘贴视频的链接,网站会自动将视频保存在您的PC上。
对于不想费事更改URL的人来说,这是一个合适的选择。只需单击一下,您就可以在您的计算机上下载任何YouTube视频。更好的是所有这些都是免费提供的,这意味着您无需支付一分钱即可下载油管视频。请按照以下步骤下载视频:
1. 打开YouTube并复制您要下载的视频链接。
2. 转到第三方网站并将链接粘贴到给定的文本栏中。
3. 点击“Go”并选择视频质量。这会将视频保存在您的计算机上,您可以随时观看。
或者,点击页面中的“Download Video”,可以跳转到视频下载页面。
继续,点击页面中视频右下角的三个点标志。
即可看到下载按钮,点击开始下载视频。
方法:在Firefox浏览器中使用YouTube Downloader插件
在Mozilla Firefox浏览器中的“扩展”选项卡搜索“YouTube Downloader”,找到后,安装扩展程序并播放您要下载的YouTube视频。
现在,只需从列表中选择你想要的视频质量,进行下载即可,视频将保存在您的电脑上。使用此扩展程序的主要优点是您可以单独下载mp3文件,如果您只想保存音轨而不需要视频,这将很有帮助;另外,使用它,我们还可以下载p超高清视频。
方法:在Opera浏览器中使用YouTube Video and Audio Downloader插件
YouTube Video and Audio Downloader是Opera浏览器的专用扩展程序,允许用户从YouTube下载mp4视频及mp3格式音频。凭借其一键下载功能,您将能够在几秒钟内开始下载所需的视频。
方法:在电脑上使用Ddownr
Ddownr是一款快速、安全且免费的在线下载器,让您无需软件即可下载高质量的YouTube视频。您需要做的就是按照以下步骤操作:
1. 复制您要从YouTube下载的视频的URL。
2. 将视频URL粘贴到Ddownr。
3. 单击下载以指定播放列表中的视频分辨率(支持P的MP4和最高8K的WEBM视频格式)。
4. 准备就绪后,视频会以ZIP文件的形式下载到您的计算机上。
方法:在电脑上使用Y2mateTV
Y2mate是油管顶级下载工具之一,可让您在没有软件的情况下以高清质量下载YouTube视频。它还支持所有格式并且非常易于使用,您需要做的就是按照以下步骤操作:
1. 搜索要下载的视频的名称或复制粘贴视频的链接。
2. 选择视频/音频格式,然后单击“下载”。
3. 等到转换完成后再下载文件。
Y2mate YouTube Converter不仅是一个视频转换器,还是一个音频转换器。您可以轻松地将 YouTube 视频、**、音乐、在线课程、MTV、播放列表等转换为您想要的格式,例如 MP4、kbps MP3。 MOV、WMV、AVI、FLV、MKV、M4A、MKA、WAV、AAC、FLAC、AIFF、OGG(所有这些格式都可以在桌面软件上使用)。MP3、MP4格式兼容多种设备,可以在Windows、Mac、iPhone、iPad、Android手机上流畅播放和观看。在线 Y2mate YouTube 转换器完全支持标清、高清P、全高清P、超高清4K视频。
方法:在电脑上使用KeepVid
Keepvid拥有一体化视频解决方案,这意味着对您而言,无需任何软件即可下载YouTube视频。
Keepvid允许您在任何网站上下载视频,淘店源码并提供在线视频转换器、在线视频压缩器、在线视频编辑器等等工具。使用Keepvid,您只需按照以下步骤操作:
1. 从YouTube视频页面复制链接。
2. 将链接粘贴到Keepvid网站的顶部文本框中。
3. 选择视频格式,开始下载。
方法:在电脑上使用YTMP3
YTMP3是下载速度最快的站点之一,并且可以免费使用。它还可以将YouTube视频转换为kbps mp3格式。要在Ytmp3上下载视频,您需要做的就是:
1. 复制您要下载的视频的URL链接。
2. 等待几秒钟以获取下载选项。
3. 单击红色的“下载”按钮,视频立即开始下载。
只需单击一下,整个视频和音乐世界供您欣赏。使用YTMP3 YouTube转换器将油管视频转换为MP3、MP4、M4A 格式。除了YouTube,YTMP3转换器还支持1,多个流行的流媒体网站,提供高速下载和无损转换。
支持的格式:mp3,mp4,HD mp4,m4a,webm,MOV,AVI,MKV,3GP,WAV,MKA;
支持的网站:YouTube、Facebook、Instagram、Vimeo、Reddit、SoundCloud、Twitter、Lynda、VEVO、Liveleak、Bilibili、BBC、Foxnews、MTV、NBC、Coub、Vlive、Einthusan、MixCloud 和更多在线视频/音乐门户。
支持的视频分辨率:p、p、p、p、p、p、4K。
支持的MP3比特率: kbps、 kbps、 kbps、 kbps。
方法:在电脑上使用ClipGrab
ClipGrab是适用于Mac、Windows和Linux用户的免费程序。它是开源的,但源代码仅适用于Linux。访问ClipGrab.org,然后单击显示所有下载选项,您将在那里看到Mac、Windows和Linux的下载链接。我将在本文中向您展示Mac版本,这三个版本的界面几乎相同,使用方法是一样的。
1. 复制YouTube视频的链接。您可以在浏览器的URL栏中执行此操作,或单击视频本身下方的“共享”按钮。
2. 启动ClipGrab,确保您位于“Downloads”选项卡上。
3. 粘贴您要下载的视频的URL。
4. 最后,单击“Grab This Clip”。
您可以调整一些选项。
例如,您可以选择视频在计算机上存储时的格式。我通常选择Original,但如果这不起作用,我会指定其他内容。
您还可以选择下载的分辨率。根据视频的原始分辨率,您可以选择下载全分辨率视频或降低分辨率以节省空间。
最后,点击“Settings”选项卡可让您自定义ClipGrab将新下载的视频存放在何处。
方法:在电脑上使用VLC Media Player
VLC媒体播放器几乎可以播放所有类型的媒体文件,它还可以用于下载YouTube视频,方法如下(如果遇到任何问题,请尝试重新安装VLC并清除缓存以使其正常工作):
1. 如果您的Windows PC上还没有该程序,请下载并安装最新版本的VLC媒体播放器。
2. 将YouTube视频的URL复制到剪贴板。
3. 打开VLC并单击左上角的媒体菜单,选择打开网络流。
4. 将复制的视频地址粘贴到“Please enter the network URL”框中,点击播放。油管视频将开始在VLC中播放。
5. 现在转到Tools Codec并从窗口底部的位置框中复制长URL。
6. 将此URL粘贴到浏览器的地址栏中,然后单击“OK”,视频将在新选项卡中开始播放。
右键单击,并选择“将视频另存为”以将YouTube视频下载为MP4文件。
方法:在电脑上使用4K Video Downloader
4K Video Downloader可以抓取质量高达8K的视频,并提供多种下载格式。只需复制油管视频的URL并单击粘贴链接按钮即可开始。
4KVD甚至可以抓取字幕、整个播放列表以及您订阅的频道中的所有视频。支持的网站仅限于YouTube、Vimeo、Facebook和其他一些知名网站,免费版本每天只能下载个视频。
如果您想同时下载超过个视频或订阅YouTube频道以立即下载最新视频,则需要付费版本。该程序本身具有将音频提取为MP3格式的选项,因此您不需要另外配套软件。此软件的使用方法如下:
1. 下载安装4K Video Downloader,并打开程序。
2. 找到一个YouTube视频并复制链接。
3. 单击菜单中的“Paste Link”。
4. 从视频质量和格式选项列表中进行选择,然后单击下载。
5. 下载视频后,单击三点图标,您可以播放或在计算机上找到它并执行其他操作。
方法:在电脑上使用5KPlayer
5KPlayer不仅仅是一个下载器,而是一个集成的下载器。承诺没有病毒、广告或插件要求,您必须先注册才能在多个站点上获得完整的下载功能。但是,您仍然可以在不注册的情况下从YouTube获取4K视频。
1. 粘贴YouTube视频的URL后,仅显示几个下载选项。
2. 单击齿轮图标,然后单击“全部显示”按钮,然后滚动查看更多信息,例如WebM格式的4K 3, x 2, 文件。MB WebM 测试下载耗时6.5分钟。
5K播放器还具有DLNA服务器播放功能,因此您可以在任何支持DLNA的设备上观看您抓取的视频,此外它还支持AirPlay以快速播放到 Apple设备。在库中选择一个视频以快速转换为MP4、MP3 甚至 ACC(iOS 首选的音频格式)。不过,它的播放器不方便播放过大的4K文件,容易遇到缓冲问题。
方法:使用iPhone或iPad下载视频
在iPhone和iPad上下载YouTube视频有点麻烦,因为Apple会监管其商店中的应用程序。如果你越狱你的手机,还有更多的选择,但如果你不想走那条路,以下是最简单的方法:
1. 下载并打开Documents by Readdle应用程序。
2. 点击指南针图标打开网络浏览器并转到online video downloader。
3. 在文本框中粘贴YouTube视频链接,然后点击“下载”。片刻之后,视频将解码并生成不同输出格式和质量选项的列表。
4. 点击首选输出选项上的“下载”。
5. 输入视频的名称和下载位置。
6. 点击底部导航栏中的下载部分,在Documents应用程序中查看您下载的视频。
7. 要将下载的视频保存到iPhone或iPad中,请返回Documents应用程序主屏幕并打开您的下载文件夹。
8. 找到您想要的视频,然后点击上面的三个点图标。
9. 点击分享,然后保存视频。
. 您可以在照片应用中找到下载的油管视频。
如何找到最新的YouTube视频下载工具
时间久了,难免有些YouTube视频下载器会失效,这里教大家一个简单的方法找到最新版本可用的油管视频下载工具。你只需要在Google里搜索:youtube downloader即可,肯定能够找到可以用的:
关于受版权保护内容的说明
YouTube的条款中允许通过官方应用下载视频,该视频无法在应用之外观看,并且您无权获取源文件。但是,如果您通过第三方工具下载 油管视频,则需要了解YouTube的服务条款 (ToS) 和版权法。如果发现您违反此规定,YouTube可以暂停或终止您的帐户。其次,您需要确保您没有违反版权法。可以合法下载的视频包括:
无版权的公共领域视频。视频受知识共享 (CC) 许可保护,YouTube包含一个搜索过滤器,用于搜索属于此许可的视频。已给您授权的朋友或家人创建的视频。
VLC播放器
VLC播放器是一款备受赞誉的开源多媒体播放器,它以其广泛的功能和跨平台的兼容性而知名。它能够流畅播放多种格式的视频,如MPEG-1、MPEG-2、MPEG-4、DivX,以及DVD/VCD的内容,甚至包括数字卫星和地球电视节目。通过IPv4和IPv6网络,它在各种作业平台下都能实现在线视频的播放,无论是本地多媒体文件还是网络流媒体,都能轻松应对。
这款软件起源于法国,由一群全球学生和开发者共同打造,其设计初衷是为用户提供多平台的支持。除了基本的播放功能,VLC还提供了基于浏览器的多媒体插件,如Mozilla-plugin-vlc,以增强用户的浏览体验。
对于那些寻求详细文档和教程的用户,VideoLAN流媒体解决方案提供了丰富的文档资料,总大小为.0MB,安装时的占用空间为.2MB。目前的版本是1.1.9-1ubuntu1(VLC),并遵循开放源代码系统,这意味着用户可以自由地使用、修改和分发。
VLC兼容多种操作系统,包括Windows、Mac OS X、iOS,以及各种Linux发行版,如Ubuntu、openSUSE、Fedora等。此外,它还支持FreeBSD、NetBSD、OpenBSD、Solaris、Android等其他操作系统,以及QNX、Syllable和OS/2等特定环境。无论你使用的是哪种系统,都能在官方网站找到对应的下载选项。
ffplay视频播放原理分析
作者|赵家祝FFmpeg框架由命令行工具和函数库组成,ffplay是其中的一种命令行工具,提供了播放音视频文件的功能,不仅可以播放本地多媒体文件,还可以播放网络流媒体文件。本文从ffplay的整体播放流程出发,借鉴其设计思路,学习如何设计一款简易的播放器。
一、播放器工作流程在学习ffplay源码之前,为了方便理解,我们先宏观了解一下播放器在播放媒体文件时的工作流程。
解协议:媒体文件在网络上传输时,需要经过流媒体协议将媒体数据分段成若干个数据包,这样就可以满足用户一边下载一边观看的需求,而不需要等整个媒体文件都下载完成才能观看。常见的流媒体协议有RTMP、HTTP、HLS、MPEG-DASH、MSS、HDS等。由于流媒体协议中不仅仅包含媒体数据,还包含控制播放的信令数据。因此,解协议是移除协议中的信令数据,输出音视频封装格式数据。
解封装:封装格式也叫容器,就是将已经编码压缩好的视频流和音频流按照一定的格式放到一个文件中,常见的封装格式有MP4、FLV、MPEG2-TS、AVI、MKV、MOV等。解封装是将封装格式数据中的音频流压缩编码数据和视频流压缩编码数据分离,方便在解码阶段使用不同的解码器解码。
解码:压缩编码数据是在原始数据基础上采用不同的编码压缩得到的数据,而解码阶段就是编码的逆向操作。常见的视频压缩编码标准有H./H.、MPEG-2、AV1、V8/9等,音频压缩编码标准有AAC、MP3等。解压后得到的视频图像数据是YUV或RGB,音频采样数据是PCM。
音视频同步:解码后的视频数据和音频数据是独立的,在送给显卡和声卡播放前,需要将视频和音频同步,避免播放进度不一致。
二、main函数ffplay的使用非常简单,以ffplay-iinput.mp4-loop2为例,表示使用ffplay播放器循环播放input.mp4文件两遍。执行该命令时,对应的源码在fftools/ffplay.c中,程序入口函数是main函数。
注:本文ffplay源码基于ffmpeg4.4。
2.1环境初始化
初始化部分主要调用以下函数:
init_dynload:调用SetDllDirectory("")删除动态链接库(DLL)搜索路径中的当前工作目录,是Windows平台下的一种安全预防措施。
av_log_set_flag:设置log打印的标记为AV_LOG_SKIP_REPEATED,即跳过重复消息。
parse_loglevel:解析log的级别,会匹配命令中的-loglevel字段。如果命令中添加-report,会将播放日志输出成文件。
avdevice_register_all:注册特殊设备的封装库。
avformat_network_init:初始化网络资源,可以从网络中拉流。
parse_options:解析命令行参数,示例中的-iinput.mp4和-loop2就是通过这个函数解析的,支持的选项定义在options静态数组中。解析得到的文件名、文件格式分别保存在全局变量input_filename和file_iformat中。
2.2SDL初始化
SDL的全称是SimpleDirectMediaLayer,是一个跨平台的多媒体开发库,支持Linux、Windows、MacOS等多个平台,实际上是对DirectX、OpenGL、Xlib再封装,在不同操作系统上提供了相同的函数。ffplay的播放显示是通过SDL实现的。
main函数中主要调用了以下三个SDL函数:
SDL_Init:初始化SDL库,传入的参数flags,默认支持视频、音频和定时器,如果命令中配置了-an则禁用音频,配置了-vn则禁用视频。
SDL_CreateWindow:创建播放视频的窗口,该函数可以指定窗口的位置、大小,默认是*大小。
SDL_CreateRenderer:为指定的窗口创建渲染器上下文,对应的结构体是SDL_Render。我们既可以使用渲染器创建纹理,也可以渲染视图。
2.3解析媒体流
stream_open函数是ffplay开始播放流程的起点,该函数传入两个参数,分别是文件名input_filename和文件格式file_iformat。下面是函数内部的处理流程:
(1)初始化VideoState:VideoState是ffplay中最大的结构体,所有的视频信息都定义在其中。初始化VideoState时,先定义VideoState结构体指针类型的局部变量is,分配堆内存。然后初始化结构体中的变量,例如视频流、音频流、字幕流的索引,并赋值函数入参filename和iformat。
(2)初始化FrameQueue:FrameQueue是解码后的Frame队列,Frame是解码后的数据,例如视频解码后是YUV或RGB数据,音频解码后是PCM数据。初始化FrameQueue时,会对VideoState中的pictq(视频帧队列)、subpq(字幕帧队列)、sampq(音频帧队列)依次调用frame_queue_init函数进行初始化。FrameQueue内部是通过数组实现了一个先进先出的环形缓冲区,windex是写指针,被解码线程使用;rindex是读指针,被播放线程使用。使用环形缓冲区的好处是,缓冲区内的元素被移除后,其它元素不需要移动位置,适用于事先知道缓冲区最大容量的场景。
(3)初始化PacketQueue:PacketQueue是解码前的Packet队列,用于保存解封装后的数据。初始化PacketQueue时,会对VideoState中的videoq(视频包队列)、audio(音频包队列)、subtitleq(字幕包队列)依次调用packet_queue_init函数进行初始化。不同于FrameQueue,PacketQueue采用链表的方式实现队列。由于解码前的包大小不可控,无法明确缓冲区的最大容量,如果使用环形缓冲区,容易触发缓冲区扩容,需要移动缓冲区内的数据。因此,使用链表实现队列更加合适。
(4)初始化Clock:Clock是时钟,在音视频同步阶段,有三种同步方法:视频同步到音频,音频同步到视频,以及音频和视频同步到外部时钟。初始化Clock时,会对VideoState中的vidclk(视频时钟)、audclk(音频时钟)、extclk(外部时钟)依次调用init_clock函数进行初始化。
(5)限制音量范围:先限制音量范围在0~之间,然后再根据SDL的音量范围作进一步限制。
(6)设置音视频同步方式:ffplay默认采用AV_SYNC_AUDIO_MASTER,即视频同步到音频。
(7)创建读线程:调用SDL_CreateThread创建读线程,同时设置了线程创建成功的回调read_thread函数以及接收参数is(stream_open函数最开始创建的VideoState指针类型的局部变量)。如果线程创建失败,则调用stream_close做销毁逻辑。
(8)返回值:将局部变量is作为函数返回值返回,用于处理下面的各种SDL事件。
2.4SDL事件处理
event_loop函数内部是一个for循环,使用SDL监听用户的键盘按键事件、鼠标点击事件、窗口事件、退出事件等。
三、read_thread函数read_thread函数的作用是从磁盘或者网络中获取流,包括音频流、视频流和字幕流,然后根据可用性创建对应流的解码线程。因此read_thread所在的线程实际上起到了解协议/解封装的作用。核心处理流程可以分为以下步骤:
3.1创建AVFormatContext
AVFormatContext是封装上下文,描述了媒体文件或媒体流的构成和基本信息。avformat_alloc_context函数用于分配内存创建AVFormatContext对象ic。
拿到AVFormatContext对象后,在调用avformat_open_input函数打开文件前,需要设置中断回调函数,用于检查是否应该中断IO操作。
?ic->interrupt_callback.callback=decode_interrupt_cb;ic->interrupt_callback.opaque=is;decode_interrupt_cb内部返回了一个VideoState的abort_request变量,该变量在调用stream_close函数关闭流时会被置为1。
3.2打开输入文件
在准备好前面的一些赋值操作后,就可以开始根据filename打开文件了。avformat_open_input函数用于打开一个文件,并对文件进行解析。如果文件是一个网络链接,则发起网络请求,在网络数据返回后解析音频流、视频流相关的数据。
3.3搜索流信息
搜索流信息使用avformat_find_stream_info函数,该从媒体文件中读取若干个包,然后从其中搜索流相关的信息,最后将搜索到的流信息放到ic->streams指针数组中,数组的大小为ic->nb_streams。
由于在实际播放过程中,用户可以指定是否禁用音频流、视频流、字幕流。因此在解码要处理的流之前,会判断对应的流是否处于不可用状态,如果是可用状态则调用av_find_best_stream函数查找对应流的索引,并保存在st_index数组中。
3.4设置窗口大小
如果找到了视频流的索引,则需要渲染视频画面。由于窗体的大小一般使用默认值*,这个值和视频帧真正的大小可能是不相等的。为了正确显示承载视频画面的窗体,需要计算视频帧的宽高比。调用av_guess_sample_aspect_ration函数猜测帧样本的宽高比,调用set_default_window_size函数重新设置显示窗口的大小和宽高比。
3.5创建解码线程
根据st_index判断音频流、视频流、字幕流的索引是否找到,如果找到了就依次调用stream_component_open创建对应流的解码线程。
3.6解封装处理
接下来是一个for(;;)循环:
(1)响应中断停止、暂停/继续、Seek操作;
(2)判断PacketQueue队列是否满了,如果满了就休眠ms,继续循环;
(3)调用av_read_frame从码流中读取若干个音频帧或一个视频帧;
(4)从输入文件中读取一个AVPacket,判断当前AVPacket是否在播放时间范围内,如果是则调用packet_queue_put函数,根据类型将其放在音频/视频/字幕的PacketQueue中。
四、stream_component_open函数3.5小节讲到,stream_component_open函数负责创建不同流的解码线程。那么它是如何创建解码线程的呢?
4.1创建AVCodecContext
AVCodecContext是编解码器上下文,保存音视频编解码相关的信息。使用avcodec_alloc_context3函数分配空间,使用avcodec_free_context函数释放空间。
4.2查找解码器
根据解码器的id,调用avcodec_find_decoder函数,查找对应的解码器。与之类似的一个函数是avcodec_find_encoder,用于查找FFmpeg的编码器。两个函数返回的结构体都是AVCodec。
如果指定了解码器名称,则需要调用avcodec_find_decoder_by_name函数查找解码器。
不管是哪种方式查找解码器,如果没有找到解码器,都会抛异常退出流程。
4.3解码器初始化
找到解码器后,需要打开解码器,并对解码器初始化,对应的函数是avcodec_open2,该函数也支持编码器的初始化。
4.4创建解码线程
判断解码类型,创建不同的解码线程。
switch(avctx->codec_type){ caseAVMEDIA_TYPE_AUDIO://音频...if((ret=decoder_init(&is->auddec,avctx,&is->audioq,is->continue_read_thread))<0)gotofail;...if((ret=decoder_start(&is->auddec,audio_thread,"audio_decoder",is))<0)gotoout;...caseAVMEDIA_TYPE_VIDEO://视频...if((ret=decoder_init(&is->viddec,avctx,&is->videoq,is->continue_read_thread))<0)gotofail;if((ret=decoder_start(&is->viddec,video_thread,"video_decoder",is))<0)gotoout;...caseAVMEDIA_TYPE_SUBTITLE://字幕...if((ret=decoder_init(&is->subdec,avctx,&is->subtitleq,is->continue_read_thread))<0)gotofail;if((ret=decoder_start(&is->subdec,subtitle_thread,"subtitle_decoder",is))<0)gotoout;...}线程创建在decoder_start函数中,依然使用SDL创建线程的方式,调用SDL_CreateThread函数。
五、video_thread函数视频解码线程从视频的PacketQueue中不断读取AVPacket,解码完成后将AVFrame放入视频FrameQueue。音频的解码实现和视频类似,这里仅介绍视频的解码过程。
5.1创建AVFrame
AVFrame描述解码后的原始音频数据或视频数据,通过av_frame_alloc函数分配内存,通过av_frame_free函数释放内存。
5.2视频解码
开启for(;;)循环,不断调用get_video_frame函数解码一个视频帧。该函数主要调用了decoder_decode_frame函数解码,decoder_decode_frame函数对音频、视频、字幕都进行了处理,主要依靠FFmpeg的avcodec_receive_frame函数获取解码器解码输出的数据。
拿到解码后的视频帧后,会根据音视频同步的方式和命令行的-framedrop选项,判断是否需要丢弃失去同步的视频帧。
命令行带-framedrop选项,无论哪种音视频同步机制,都会丢弃失去同步的视频帧。
命令行带-noframedrop选项,无论哪种音视频同步机制,都不会丢弃失去同步的视频帧。
命令行不带-framedrop或-noframedrop选项,若音视频同步机制为同步到视频,则不丢弃失去同步的视频帧,否则会丢弃失去同步的视频帧。
5.3放入FrameQueue
调用queue_picture函数,将AVFrame放入FrameQueue。该函数内部调用了frame_queue_push函数,采用了环形缓冲区的处理方式,对写指针windex累加。
staticvoidframe_queue_push(FrameQueue*f){ if(++f->windex==f->max_size)f->windex=0;SDL_LockMutex(f->mutex);f->size++;SDL_CondSignal(f->cond);SDL_UnlockMutex(f->mutex);}六、音视频同步ffplay默认采用将视频同步到音频的方式,分以下三种情况:
如果视频和音频进度一致,不需要同步;
如果视频落后音频,则丢弃当前帧直接播放下一帧,人眼感觉跳帧了;
如果视频超前音频,则重复显示上一帧,等待音频,人眼感觉视频画面停止了,但是有声音在播放;
ffplay视频同步到音频的逻辑在视频播放函数video_refresh中实现。该函数的调用链是:main()->event_loop()->refresh_loop_wait_event()->video_refresh。
6.1判断播放完成
调用frame_queue_nb_remaing函数计算剩余没有显示的帧数是否等于0,如果是,则不需要走剩下的步骤。计算过程比较简单,用FrameQueue的size-rindex_shown,size是FrameQueue的大小,rindex_shown表示rindex指向的节点是否已经显示,如果已经显示则为1,否则为0。
6.2播放序列匹配
****分别调用frame_queue_peek_last和frame_queue_peek函数从FrameQueue中获取上一帧和当前帧,上一帧是上次已经显示的帧,当前帧是当前待显示的帧。
(1)比较当前帧和当前PacketQueue的播放序列serial是否相等:
如果不等,重试视频播放的逻辑;
如果相等,则进入(2)流程判断;
注:serial是用来区分是不是连续的数据,如果发生了seek,会开始一个新的播放序列,
(2)比较上一帧和当前帧的播放序列serial是否相等:
如果不相等,则将frame_timer更新为当前时间;
如果相等,不处理并进入下一流程
6.3判断是否重复上一帧
(1)将上一帧lastvp和当前帧vp传入vp_duration函数,通过vp->pts-lastvp->pts计算上一帧的播放时长。
注:pts全称是PresentationTimeStamp,显示时间戳,表示解码后得到的帧的显示时间。
(2)在compute_target_delay函数中,调用get_clock函数获取视频时钟,调用get_master_clock函数获取同步时钟,计算两个时钟的差值,根据差值计算需要delay的时间。
(3)如果当前帧播放时刻(is->frame_timer+delay)大于当前时刻(time),表示当前帧的播放时间还没有到,相当于当前视频超前音频了,则需要将上一帧再播放一遍。
last_duration=vp_duration(is,lastvp,vp);delay=compute_target_delay(last_duration,is);time=av_gettime_relative()/.0;if(time<is->frame_timer+delay){ *remaining_time=FFMIN(is->frame_timer+delay-time,*remaining_time);gotodisplay;}6.4判断是否丢弃未播放的帧
如果当前队列中的帧数大于1,则需要考虑丢帧,只有一帧的时候不考虑丢帧。
(1)调用frame_queue_peek_next函数获取下一帧(下一个待显示的帧),根据当前帧和下一帧计算当前帧的播放时长,计算过程和6.3相同。
(2)满足以下条件时,开始丢帧:
当前播放模式不是步进模式;
丢帧策略生效:framedrop>0,或者当前音视频同步策略不是音频到视频。
当前帧vp还没有来得及播放,但是下一帧的播放时刻(is->frame_timer+duration)已经小于当前系统时刻(time)了。
(3)丢帧时,将is->frame_drops_late++,并调用frame_queue_next函数将上一帧删除,更新FrameQueue的读指针rindex和size。
if(frame_queue_nb_remaining(&is->pictq)>1){ Frame*nextvp=frame_queue_peek_next(&is->pictq);duration=vp_duration(is,vp,nextvp);if(!is->step&&(framedrop>0||(framedrop&&get_master_sync_type(is)!=AV_SYNC_VIDEO_MASTER))&&time>is->frame_timer+duration){ is->frame_drops_late++;frame_queue_next(&is->pictq);gotoretry;}}七、渲染ffplay最终的图像渲染是由SDL完成的,在video_display中调用了SDL_RenderPresent(render)函数,其中render参数是最开始在main函数中创建的。在渲染之前,需要将解码得到的视频帧数据转换为SDL支持的图像格式。转换过程在upload_texture函数中实现,细节不在此处分析。
音频类似,如果解码得到的音频不能被SDL支持,需要对音频进行重采样,将音频帧格式转换为SDL支持的格式。
八、小结本文从整体播放流程出发,介绍了ffplay播放器播放媒体文件的主要流程,不深陷于代码细节。同时,对FFmpeg的一些常用函数有了一些了解,对我们自己手写一个简单的播放器有很大的帮助。
----------END----------