JCHub

  • Home
  • Category
    • A/V
    • WebRTC
    • Beauty of Programming
    • Linux
    • Windows
    • Moments of Life
    • Campus Life
  • Reference
    • API Reference
    • Utilities
    • AV Test
    • Doc
  • Message Board
  • About
A/V
A/V

Windows平台WebRTC编译-VS2017

在音视频领域,想深入研究的话,必定会接触WebRTC。WebRTC是一个庞大的工程,就像是音视频领域的百科全书,音视频采集,编解码,传输,渲染等一条龙在WebRTC里都有,而且WebRTC还有很多先进的音视频处理算法。由于WebRTC代码过于庞大,所以最好单步调试跟踪代码运行,这样才可以更好地学习WebRTC,否则很难有头绪。工欲善其事必先利其器,作为调试神器,宇宙第一IDE Visual Studio必不可少。所以本篇文章主要讲下如何在Windows上编译WebRTC,同时得到VS工程,然后调试。 本文内容截止2020.04.01,最新代码测试编译通过。最新VS2017以上版本编译见文末。 系统要求 Win7及以上64位系统。 内存至少8G,当然越大越好。 至少50G磁盘空间(NTFS格式),不能是FAT32,因为会生成大于4G的文件。 Visual Studio安装 WebRTC用到了很多C++最新特性,所以编译最新WebRTC代码VS要求为2017(>=15.7.2) 版本。我用的是VS2017社区版(VS新老版本下载)。VS最好安装在C盘,按默认路径安装,否则可能遇到问题(见问题0x02)。安装VS2017时选择自定义安装,必须勾选如下几项: Desktop development with C++组件中10.0.18362或以上的Win10 SDK,后面还要安装调试工具 Desktop development with C++组件中MFC以及ATL这两项 2020.04.01更新:由于最新WebRTC源码要求10.0.18362及以上Win10 SDK。所以请下载10.0.18362 或以上的Win10 SDK。本文写于2019年,那时VS2019还没发布。由于10.0.18362 Win10 SDK存在于VS2019安装选项中,VS2017安装选项不带有该SDK,所以使用VS2017得从Win10 SDK下载另外下载最新Win10 SDK,或者再装个VS2019选择安装该SDK 安装完VS2017后,必须安装SDK调试工具。打开控制面板->程序与功能,找到刚才安装的最新Windows Software Development Kit,鼠标右键->change。 勾选Debugging Tools For Windows,然后点击change。 depot_tools安装 下载depot_tools然后解压到某个目录,比我的解压到E盘根目录。接着将该depot_tools目录的路径加到系统环境变量Path里,然后把该路径移到最前面(避免已安装的python与git造成影响)。 获取WebRTC源码 由于WebRTC的源码地址被墙了,所以需要通过代理或者vpn才能得到源码。后面都是命令行操作,打开cmd窗口,由于我用的是ss代理,在cmd窗口我按如下设置: [crayon-69c7c12981bb9737129509/] 设置当前cmd窗口代理上网,如果cmd窗口关闭了重开得重新设置。当然了,也可以设置系统全局代理上网。其他代理方法也类似。如果是VPN之类非代理,就不用这样设置了。 接着执行gclient命令,安装编译需要用到的一些工具,比如git以及python。 [crayon-69c7c12981bc5866553574/] 再接着设置一些环境变量,设置下我们的VS安装路径。 [crayon-69c7c12981bc9507158040/] 然后cd到要放源码的地方(要遵守前面说的磁盘要求),执行: [crayon-69c7c12981bcc820564073/] 这一过程是个漫长的等待,要下的东西将近10G,包括源码以及一些测试的音视频文件资源等,如果因为网络等原因中断了,就再执行gclient sync。如果这一步一直卡着不动,可以执行ctrl+c,然后执行gclient sync。 使用gclient sync可能遇到的问题 问题0x01 [crayon-69c7c12981bcf880193451/] Unicode字符编码问题,python的一个bug,因为很多人系统语言都是中文的,所以得按如下设置,把系统区域改为英文,然后重启即可。 问题0x02 2019.04.01更新。去年的版本我编译时没报这个问题,我看到评论里有人提出来了,我下了今天的最新代码,编译时也碰到了,看了下是最新WebRTC windows相关脚本变化导致 报Exception: No supported Visual Studio can be found. Supported versions are: 16.0 (2019), 15.0 (2017)错误: [crayon-69c7c12981bd2804023964/] 解决方法为修改src\build目录下的vs_toolchain.py脚本,加了一行,直接写死我们的VS路径代码: [crayon-69c7c12981bd5534931742/] 脚本中的代码默认以C盘处理的,如果我们的VS安装在C盘默认目录就不会报这个错,但我想很多人VS不会装在C盘。 执行:python src/build/vs_toolchain.py get_toolchain_dir验证修改,控制台打印如下: [crayon-69c7c12981bd9765433058/] 说明修改成功。接着我们使用gclient sync会报如下问题: [crayon-69c7c12981bdd979823090/] 因为我们修改了脚本,所以执行gclient sync --force即可。 gclient sync --force成功结束后,vs_toolchain.py文件会被还原,所以得按前面重新修改vs_toolchain.py。vs_toolchain.py中会优先选择高版本VS编译,由于本文使用VS2017编译,假如我们电脑安装有VS2019,需要按如下修改,把VS2017放前面,避免造成影响。 [crayon-69c7c12981be0126124175/] 编译 生成VS2017工程文件: [crayon-69c7c12981be3638047267/] 可以在src\out\Default\ 下得到 all.sln解决方案文件。 如果不想使用默认编译参数,可以使用gn args out/Default --list查看当前编译参数,通过类似如下方式设置: [crayon-69c7c12981be6474071520/] 接着执行编译命令: [crayon-69c7c12981be9489196197/] 用VS2017打开: 可以看到众多工程,到此算是完成了。找到我们感兴趣的,就可以用VS单步调试,跟踪代码运行了。这么多宝贝够研究很久了。 代码更新 [crayon-69c7c12981bed112542554/] 引用WebRTC库 WebRTC编译后会在src\out\Default\obj目录下生成整个WebRTC工程的静态库:webrtc.lib,链接下这个就可以了。 总结 总之WebRTC在Windows上的编译很考验耐心,也很苛刻,需要有个好的访问被墙地址工具。最新VS2019编译可以参考我的这篇文章: Windows平台WebRTC编译(持续更新),本文也不再更新。 参考 1. WebRTC Native code Development 2. Chromium’s build instructions for Windows

2019年3月14日 91comments 40674hotness 30likes Jeff Read all
A/V

Ubuntu vaapi-ffmpeg开发环境搭建

本篇文章有些内容比较过时,最新请参考:https://blog.jianchihu.net/intel-gpu-hw-video-codec-develop.html。包含CentOS以及Ubuntu的开发环境搭建 最近要在Linux上做编解码开发,为了成本考虑,没用NVIDIA的方案,用了Intel编解码方案。大家都知道Intel在Windows上有个Intel Media SDK的方案,比较常用,支持的CPU型号也多,在Linux上也有类似方案,叫做Intel Media Server Studio。但是Intel Media Server Studio支持的型号比较少,如下是官方文档说明的支持型号: [crayon-69c7c129857a1601072009/] 不过还有一个叫做VA API(Video Acceleration API) 的方案,VA API是一个统一的编解码规范,类似Windows上的Dxva方案,主要由各大显卡厂商在驱动中实现。目前主要Intel与AMD实现这个VA API方案,不过AMD上支持的编解码特性比较少,也只是部分支持。对于Intel来说,基本上带集显的都支持VA API。所以为了成本,通用性考虑,我选用了这个VA API做Linux上的编解码开发。 如果基于原生VA API开发的话,比较复杂点,好在ffmpeg支持VA API,所以我们只需要编译支持VA API的ffmpeg即可。本篇文章主要讲下VA API开发环境的搭建,主要针对H264编解码。开发系统为ubuntu18.04.2 LTS server版本。需要注意的是,目前没看到好的显卡直通(passthrough)以及虚拟化方案,我们还是老实在实体机Linux开发,不能在虚拟机里,要不就用不了显卡硬件加速了。 基本库安装 [crayon-69c7c129857ab838746931/] VA API相关库驱动安装 Libva Libva是VA API的实现。 [crayon-69c7c129857af524458019/] intel-vaapi-driver 主要在我们的程序与Intel 集显之间起桥梁作用。传输打包的缓存以及命令到i965驱动(开源的intel集显驱动,已集成在Linux内核中),用于硬件加速的视频编解码,着色器处理等。 [crayon-69c7c129857b3632997133/] libva-utils 提供一系列 VA API相关的测试。比如vainfo命令,可以用来检测我们的硬件支持哪些VA API编解码特性。 [crayon-69c7c129857b6996783826/] 这一步安装完后,我们开始检测安装的成果,首先查看我们的显卡设备: [crayon-69c7c129857b9152995085/] 可以看到我的电脑有两张显卡,一张独显,一张集显。下面开始通过vainfo命令验证显卡支持情况: [crayon-69c7c129857bc786269538/] 可以看到我的AMD独显VA API支持很少,Intel集显基本都支持了。如果通过vainfo命令我们如上所示得到显卡支持情况,说明我们VA API相关驱动以及库安装成功了。下面介绍下支持VA API的ffmpeg的编译。 ffmpeg编译 参照官方编译,创建相关目录用于存放源码以及编译后的程序。 [crayon-69c7c129857bf759770384/] 安装nasm与yasm。ffmpeg一些汇编程序用到。 [crayon-69c7c129857c3930933692/] 编译安装libx264,用于软编H264。 [crayon-69c7c129857c7094905173/] 下载最新的ffmepg源码,编译。 [crayon-69c7c129857ca754646358/] 最后编译生成的静态库文件都在主目录ffmpeg_build里,用于我们的开发。ffmepg可执行程序在主目录bin下。运行ffmpeg程序,执行如下命令: [crayon-69c7c129857cd374593851/] 可以看到我们编译的ffmppeg已经支持VA API了。 VA API编解码开发 ffmepg官方example有VA API使用教程,具体可以看官方示例代码。不过需要注意的是VA API编码时,输入的YUV格式必须是NV12,其他格式YUV得转为NV12格式。官方example:vaapi_encode.c有个AVFrame(sw_frame) ,用于存放我们输入的YUV数据,该AVFrame的data[0]用于存放Y数据,data[1]存放UV数据,由于输入格式是NV12,所以data[1]中UV数据的内存布局为:UVUVUVUV···UVUV。

2019年3月8日 0comments 3641hotness 22likes Jeff Read all
A/V

安防视频播放秒开优化

在视频播放中,播放器立即出图像(秒开)非常重要。能够极大提高用户的体验度。网上有很多关于直播行业秒开的优化经验,但是没有安防GB28181的,GB28181标准视频播放跟直播还是有些不一样的,下面说下一些GB28181标准视频秒开的优化经验。 直播行业视频封装传输遵循RTMP/HLS/DASH这些标准。安防摄像头视频播放大多遵循GBT28181。目前常见的视频编码格式有H264/H265/MPEG-4/Svac,通常都封装为PS流(Program Stream,封装标准参考iso13818-1 2.5小节)格式,然后作为负载封装成RTP包传输。在直播行业,视频流的采集主要是用户的手机或者PC设备,而安防行业视频流的采集来自于各大厂商的摄像头。 视频秒开需要从播放端,发送端以及网络传输考虑。视频秒开关键点是要立马获取到关键帧,后续视频帧的解码都得参考关键帧,有了关键帧,解码器才能立刻解码,然后出图像。 发送端 发送端一般分为两种:直连的设备以及流媒体服务器。直连设备是指播放端直接连接摄像机播放。 摄像机设置 由于视频来自摄像机,无论发送端是哪种,我们都要修改摄像机的关键帧间隔(GOP),一般设置2倍的帧率。这样确保在较短时间内,能够获取到关键帧播放,设置太短,会增大数据量,设置太长会造成等待关键帧时间太久,一旦出现丢包等异常,影响较大。如下图是某款海康摄像机配置,我们配置视频帧率为25帧,关键帧(I帧)间隔为2s,即50帧。 服务器设置 如果不是摄像机直连,通过我们自己的流媒体服务器的话就需要对我们的服务器做处理。这时我们需要做关键帧缓存,确保推给播放端的流第一帧就是关键帧。在互联网直播中通常用到了CDN,很多CDN厂商都会缓存一组GOP数据。安防行业一般都是私有网络,没有CDN,那服务端具体要怎么做呢? 服务端为每一路摄像机信号维护一个关键帧缓冲区,缓存最新的一组GOP数据(关键帧以及相关的一组P帧),每当该摄像机有新关键帧数据来时,都要更新这个缓冲区 当有播放端请求某摄像机信号时,先判断当前摄像机实时流是否是关键帧第一个包 是的话直接推实时流,同时更新缓冲区 不是的话就得从关键帧缓冲区拿数据推给播放端,直到实时流来了关键帧,此时切换到从实时流推流,然后更新缓冲区 播放端 解复用(Demux) Demux是指解析视频的封装格式,得到包含的音视频原始码流,Demux时间越短,就越快得到视频流,从而加快秒开速度。我们这里的Demux过程主要是解析RTP负载数据,对于每个RTP包,去除头部12字节头部数据后就是负载数据。由于国标视频基本都是封装为PS流格式,所以需要解复用PS流,从PS流里得到原始视频数据。对于PS流的Demux有两个方法,一个是自己写,PS流结构不是很复杂,1000行以内代码可以搞定,如果嫌麻烦,还有一个方法是使用ffmpeg,对于ffmpeg如何demux PS流,可以参考ffmpeg的avio_reading例子,通过探测流的方式demux PS流。 如果是自己写的Demux程序,我们在Demux PS流需要搜索各种头部,由于存在丢包等异常情况,所以搜索头部太久时需要做处理,丢弃无用的数据,避免耗时太久。由于PS中包长度都是用两字节表示,长度为2^16,所以我们可以设置一个值,比2^16大点,当搜索的字节数大于这个值还没搜索一个PS流的包头(0x000001开头),此时就要丢弃之前数据,处理新数据,因为之前数据很大可能丢包或其他问题。 如果是使用ffmpeg做PS流的Demux,有几点需要注意。由于ffmpeg Demux未知流时,需要探测一定大小数据,甚至会尝试解码未知流,这个过程如果不做优化会耗时很久。 ffmpeg通过AVIO方式探测流格式主要通过avformat_find_stream_info函数实现,我们可以通过设置AVFormatContext的probesize与max_analyze_duration限制ffmpeg探测大小与时长,提高Demux速度,我一般按如下设置: [crayon-69c7c129863aa636383457/] 限制流分析大小64K,时长2s。但有点需要注意的是如果送入播放端首帧视频不是关键帧avformat_find_stream_info很大可能性失败,因为ffmpeg在max_analyze_duration内如果获取不到关键帧数据基本会探测失败。所以使用ffmpeg探测PS流时需要确保首帧视频就是关键帧(视频重要参数都存储在关键帧内),这样在max_analyze_duration内才能获取到PS流信息。至于如何判断PS流的关键帧数据,这个很简单,可以根据PS流头部判断,PS流封装的关键帧都含有system_header(0x000001BB开头)与program_stream_map(0x000001BC开头)。 解码 Demux得到原始视频码流后就可以开始解码了,能硬解码就硬解码,硬解码速度会优于软解,尤其在解码路数多时。 渲染 解码得到YUV或RGB数据后,我们需要渲染到屏幕显示,这是最后一步了。渲染也存在是否硬件加速的区别。比如windows平台,优先D3D硬件加速渲染,充分发挥显卡的能力,加快渲染速度。如果前面解码是用硬解码,此时也必须硬件加速渲染。否则又要搬运显存中的硬解数据到内存,由于解码后的数据一般较大,所以这个过程很耗时,同时影响性能,提高CPU占用率。 网络传输 传输分为TCP与UDP。由于TCP的特性,所以TCP获取到首帧视频耗时长点,同时延时也大。所以优先UDP传输。但是UDP传输又存在丢包,乱序等问题,造成视频花屏,所以使用UDP传输时,需要做好抗丢包,拥塞控制等处理,这个我们以后会讨论。

2019年2月23日 0comments 3192hotness 3likes Jeff Read all
A/V

vlc播放rtsp over tcp画面突然卡住问题

继完成rtmp服务器开发后,最近也写完了rtsp服务器,可以将国标ps流以及其他格式协议码流转rtsp协议输出。中间开发过程用了许多播放器测试,最常用的就是vlc。使用vlc测试过程,遇到了许多问题。今天就记录一个比较奇怪的问题。 使用rtp over udp模式播放时,没出现问题,但是使用rtp over tcp模式时,vlc播放几十秒后画面突然卡住不动了,看了vlc 的debug message没发现异常。用ffplay,live555,potplayer测了都没异常。后面换了不同版本vlc测试,更奇怪了,vlc3.0.0以及之前,3.0.5以及之后版本都正常。应该是vlc对rtp over tcp做了特殊处理。此时抓包分析rtsp交互数据,发现出现问题版本的vlc每隔一定时间除了会发送OPTIONS命令,然后还有以'$'开头的一串特殊字节,发送完这个播放画面就卡住了。为什么会卡住不播放了呢?只能看vlc源码查找问题了。 通过阅读相关源码,终于定位到了原因。这个是vlc的keep-alive机制造成的。由于vlc使用了live555做rtsp处理,所以对应处理代码在modules/access/live555.cpp这个文件里。下面结合代码说下原因。 [crayon-69c7c12986cf8194466112/] 如上函数是vlc的rtsp超时处理代码,出现问题的vlc版本没有 [crayon-69c7c12986d01309892538/] 这两行代码,我们先把这两行代码注释,分析下为什么会出现播放画面突然不动的现象。 1)rtsp交互开始vlc客户端会发送OPTIONS请求,我们服务器需要回应支持的方法。如果我们服务器回应包括GET_PARAMETER方法(可选),use_get_param就为true,然后keep-alive机制就会定时sendGetParameterCommand,否则sendOptionsCommand,我这边服务没去做GET_PARAMETER方法的支持,所以会定时收到vlc发的OPTIONS命令请求。vlc发送完OPTIONS请求命令后,开始wait_Live555_response(p_demux)。看下这个函数: [crayon-69c7c12986d06054066127/] 传入的参数中i_timeout为默认值0,所以没有超时时间,会一直等服务器响应请求。 2)我这边服务器有个命令解析类,只处理标准的命令(OPTIONS,DESCRIBE,PLAY等)。由于vlc会定时发送'$'开头数据,跟OPTIONS请求数据混在一起送到我的命令解析里,导致我这边没能正确解析,所以也没有回应vlc keep-alive机制的OPTIONS请求。我们再看下TimeoutPrevention函数,该函数进入后会: [crayon-69c7c12986d09123020944/] 由于我的服务器没有回应OPTIONS请求,所以这个锁会一直阻塞,我们看下这个锁用在哪个地方: [crayon-69c7c12986d0d697875779/] 可知由于TimeoutPrevention一直阻塞,所以Demux过程不能执行了,所以播放画面不动了。 新版vlc已经通过 [crayon-69c7c12986d10148525350/] 取消了rtp over tcp的keep-alive机制,所以3.0.5以及之后版本没有出现问题。我的rtsp服务器后面也针对'$'开头数据做了处理,测了下,一切都正常了。 '$'开头数据是做什么的呢?在我服务器发RTCP数据时才用到,没想到客户端也有类似机制。在rfc2326中,'$'(0x24)开头数据叫做:Embedded (Interleaved) Binary Data,称为嵌入式二进制数据。测试的那么多播放器,只有vlc实现了这个。而且这个Embedded (Interleaved) Binary Data只工作在rtp over tcp下。这个数据有什么作用呢?rfx2326 10.12这么介绍的: [crayon-69c7c12986d14318346982/] rtp over tcp模式下,就一个socket端口进行命令控制以及流传输,不像rtp over udp,另开udp socket传输数据。由于防火墙以及其他外部因素,可能造成rtsp方法与rtp流数据交织混在一起。为了避免这个,才有这个设计。通过: [crayon-69c7c12986d18473240110/] 对控制信息以及流数据进行区分。具体介绍可以参考: RTP over RTSP包混合发送的解决办法:https://blog.csdn.net/myslq/article/details/79819179 由于Embedded (Interleaved) Binary Data是在是在服务器回应PLAY推流后vlc才这样处理的,我这边没注意到,所以导致解析出现错误。不过除了vlc,其他播放器都没支持Embedded (Interleaved) Binary Data,因为推流是服务器端,前面命令交互完,服务器就开始推流了,对于客户端我觉得用处不大。

2018年12月23日 0comments 3673hotness 7likes Jeff Read all
A/V

Intel media SDK编码去除多余信息

使用Intel media SDK硬编码H264数据时,生成的每一帧H264数据都包含Access unit delimiter+Picture parameter set+Additional information (SEI)。如下图是使用默认参数生成的一个非IDR帧H264数据。 IDR帧数据结构如下: 根据nal uint type表 可知: 默认编码IDR帧结构:0x00 00 00 01 09(分隔符)|| 0x00 00 00 01 27(SPS)|| 0x00 00 00 01 28(PPS)|| 0x00 00 00 01 06(SEI)|| 0x00 00 01 25(IDR) 默认编码非IDR帧结构:0x00 00 00 01 09(分隔符)|| 0x00 00 00 01 28(PPS)|| 0x00 00 00 01 06(SEI)|| 0x00 00 01 21(非IDR) 但是默认编码有个问题,不是所有播放器可以支持直接播放,测了下VLC不支持(以前文章说过VLC播放带SEI的视频花屏问题),PotPlayer可以播放,这个问题在于编码出来的每帧数据都多了分隔符与SEI以及PPS,不是所有的播放器都去解析这些头部,这方面NVIDIA Video Codec硬编码就简单多了,IDR帧结构就SPS+PPS+IDR,非IDR帧就一个头部。所以为了兼容大多数播放器我们需要去掉多余的分隔符、SEI以及PPS信息,这些信息用途不大,PPS没必要每帧都带,反而增加数据量。如何去除呢,一种方法是手动解析这些头部,然后手动去除,另一种方法是使用编码的扩展参数,这个编码扩展参数如果没认真研究官方文档,还真不知道怎么用。 如下是编码扩展参数如何使用的代码。代码中我们将设置的参数放到一个数组中,然后传递给编码参数mfxVideoParam的ExtParam成员。 [crayon-69c7c12987721240556371/] mfxExtCodingOption.PicTimingSEI: Set this flag to insert the picture timing SEI with pic_struct syntax element. See sub-clauses D.1.2 and D.2.2 of the ISO /IEC 14496-10 specification for the definition of this syntax element. See the CodingOptionValue enumerator for values of this option. The default value is ON. 也就是这个成员用于在每帧插入图像时序SEI信息,默认是开启的。 mfxExtCodingOption.AUDelimite: Set this flag to insert the Access Unit Delimiter NAL. See the CodingOptionValue enumerator for values of this option.该标志用于插入分隔符。 mfxExtCodingOption2.RepeatPPS: This flag controls picture parameter set repetition in AVC encoder. Turn ON this flag to repeat PPS with each frame. See the CodingOptionValue enumerator for values of this option. The default value is ON. This parameter is valid only during initialization.用于设置AVC编码器在每一帧编码中插入PPS。默认是开启的。 通过关闭如上编码参数,即可去除多余的数据,编码生成"简洁"的H264帧。

2018年8月14日 1comments 3054hotness 4likes Jeff Read all
A/V

基于FireBreath的npapi插件在Firefox下的调试

最近要做基于浏览器的视频播放,可以播放各种格式的流。首先为了快速出产品先做一个npapi插件,没用activex,因为IE限制了前端们的想象力与创造力,H5播放技术留在最后面做。刚开始做npapi插件用的是火狐原生api开发,比较繁琐。后面找了一个叫做firebreath的开发框架,开发的插件可以在IE,firefox以及chrome旧版本使用,提高了些开发效率,不过还是很多坑,网上资料也少。 看了一天firebreath官网文档,就开始动手搭建开发环境,搭建还是很快的,下个cmake,python,按官网教程一步步来都不会有问题。 随着播放插件越来越复杂必定少不了调试了。不过发现官网给的插件调试方法用不了。官网给的方法是直接附加到firefox进程,不过进不了断点。后来摸索了下,得附加到plugin-container.exe才可以,火狐这样做也是为了安全与稳定性,将插件与标签页进程做了隔离。附加进程操作如下图: 参考链接: 1)FireBreath:http://www.firebreath.org/

2018年5月15日 0comments 2212hotness 1likes Jeff Read all
A/V

html5播放flv

好久没看优酷了,发现优酷也支持html5播放了,这样看1080p视频电脑不会呼呼叫了。看了下,优酷用的是hls方案。如下为我观看的动漫视频: 鼠标右键复制调试信息可以得到: [crayon-69c7c12988801936201014/] 其中"supportType":"hls"就说明了优酷用的hls。hls延迟比较大,像这种非直播应用问题不大。话说我还是习惯用youtube,因为youtube播放器强大多了,可以设置自动字幕翻译,而且可以实时查看调试信息。 目前大多数直播都是采用rtmp协议,延迟小,有很多现成方案,比如librtmp库推流,srs或者nginx rtmp做服务器。但是网页端播放大多还是采用flash插件,耗电,性能差,开个1080p电脑就要呼呼叫了。所以这时候就需要html5了,浏览器通过html5播放视频支持硬件加速,可以明显降低CPU负载。 html5中播放视频用的是video标签,用法:http://www.w3school.com.cn/tags/tag_video.asp。支持Ogg、MPEG4、WebM三种格式。 其中WebM主要是谷歌在使用,Youtube现在用的WebM封装的是vp9视频,接着最常见的是MP4了。 由于html5 video标签只支持mp4,要想也支持flv,我们就要拆解flv了。由于flv容器封装的是H264+AAC,所以我们可以在网页端收到flv后,使用js代码解析flv,取出H264以及AAC,然后封装成mp4文件,再喂给video标签就可以了。这样我们就可以无插件播放flv了,由于mp4封装比flv复杂多了,所以这样可以减轻服务器压力,服务器不用再专门封装mp4文件。前面说到youku用的hls,跟flv类似,也需要一个js插件把hls转成mp4。 如果要学习flv容器格式,可以参考:http://blog.jianchihu.net/flvanalyzer.html 附带的工具,这是我两年前写的。 如果要学习mp4容器格式,可以参考:http://blog.jianchihu.net/mp4-elst-box.html 附带的工具,我当初做mp4解析就是用到该工具,然后配合标准文档:http://blog.jianchihu.net/doc 基本就没问题了,源码的话可以参考ffmpeg demux模块。 市面上有很多现成方案,可以参考下bibili的flv.js。

2018年3月1日 0comments 3173hotness 3likes Jeff Read all
A/V

流媒体网络性能指标——抖动

有时候我们开发一个流媒体系统,做完了却不知道如何用数字描述我们的系统,体现我们的优势,作为客户来说,可以描述这套系统的数字指标是最直观的,尤其在网络性能这块。在流媒体网络中,影响流媒体服务质量(QOS)的因素有很多,而这些因素可以作为我们衡量流媒体网络性能的指标。 衡量流媒体网络性能的常见指标主要有: 带宽 吞吐量 延时 抖动 丢包率 本篇文章主要讲下抖动(jitter),以及如何处理抖动,本文主要针对语音通信。在网络中,每个包从发送端到接收端的时延是不相同的,而jitter就是用来衡量这种不同。在发送端数据包发送时间间隔是相同的,也就是均匀发送数据,但是由于各种情况,例如拥塞,因为网络错误导致的丢包等,接受端收到数据包间隔就会不一样了,可能一会大,一会小,这就是所谓的抖动,严重影响音质。 下面先了解下传统学术上的相关定义。 延时:记s(i), r(i)分别为第i个包的发送、接收时间戳,延时d(i) = r(i) – s(i) 抖动:jitter(i) = d(i+1) – d(i) 传统定义中,抖动仅能描述某个时刻的情况,而流媒体是持续的,我们更关注某个时间段上的情况,对比某时刻情况更实用。 为了更好描述某个时间段的抖动,我们按如下定义更实用的抖动指标(参考声网): 1)记s(i), r(i)为第i个包的发送与接收时间戳,延时d(i) = r(i) – s(i); 2)t秒为一个统计周期,集合D = {d(i) | i ∈ t秒内收到的包序号集合 }; 3)对集合D做从小到大排序,得到D(sorted); 4)对D(sorted)中每个元素,减去D中最小值min(D),得到新的集合 D(jitter)。 现在D(jitter)中元素含义就是,t秒内所有语音数据包传输延时,相对最快那个数据包的偏移,原来抖动定义是相对前一个包延时偏移。可知D(jitter)中最大元素表示传输延时最大的。 为了消除抖动,接收端要么丢帧,要么延时。一般都会引入一个缓冲区,也就是抖动缓冲(jitterbuffer)。引入了抖动缓冲后,我们可以这样处理抖动: 1)jitter > jitterbuffer length,丢帧处理; 2) jitter

2017年8月14日 5comments 5971hotness 8likes Jeff Read all
12345
Copyright Statement

Unauthorized reproduction or plagiarism in any form is strictly prohibited. For reprint requests, please contact via email.

Recent Comments
snail Published at 1 days ago(03 03202633105 27 27pm26) 多谢,大佬。醍醐灌顶!
Bramsnawl Published at 1 days ago(03 03202633110 27 27am26) Proper blood collection playing cards are measure ...
NasibDepdrotte Published at 2 days ago(03 03202633110 26 26pm26) Inf ect isC linNo rth A m viiiix, Sm ets o urgo is...
Pereplanirovka kvartir_cvsr Published at 3 days ago(03 03202633105 25 25pm26) перепланировка услуги [url=https://pereplanirovka-...
Mirzoemele Published at 3 months ago(01 01202613104 06 06pm26) Double blind randomised controlled trial of two to...
Ad

COPYRIGHT © 2026 jianchihu.net. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang