原帖地址:http://blog.csdn.net/coroutines/article/details/7472743

VLC版本2.0.1

最近研究IP-STB音视频同步问题,发现方案自带的自动STC在网络延时过大时,不能成功同步音视频。在参考了VLC的串流播放机制后,以为适当缓冲可以解决此问题,可惜最终结果是稍有缓解,并不能从根本上解决。但这种缓冲时间的计算,对于基于网络这种音视频数据的注入有一定的参考意义。

1、最初的线索:

使用 -vvv 参数 启动VLC时,提示:

命令行启动vlc: ./vlc.exe -vvv

[0xb73005f0] main input debug: Buffering 0%
[0xb73005f0] main input debug: Buffering 3%
[0xb73005f0] main input debug: Buffering 6%
[0xb73005f0] main input debug: Buffering 9%
[0xb73005f0] main input debug: Buffering 12%
[0xb73005f0] main input debug: Buffering 15%
[0xb73005f0] main input debug: Buffering 18%
[0xb73005f0] main input debug: Buffering 21%
[0xb73005f0] main input debug: Buffering 24%
[0xb73005f0] main input debug: Buffering 27%

可以查找到这个缓冲过程的打印是从src/input/es_out.c:658行输出的。函数EsOutDecodersStopBuffering的作用是判断当前缓冲流的长度i_stream_duration是否达到预置的i_buffering_duation长度,是则停止缓冲,否则返回等待。

接下来是查i_stream_duration和i_buffering_duation如何计算。

2、i_stream_duration的计算:

在EsOutDecodersStopBuffering中,i_stream_duration是通过input_clock_GetState来获取。而input_clock_GetState是取一个类型为input_clock_t对象的俩个clock_point_t对象成员last和ref的i_stream的差值作为已缓冲数据的长度。

继续查找i_stream值的计算,可以发现i_stream只有在clock_point_Create中进行的设置,而last和ref对象的i_stream值是在input_clock_Update中做了更新,而用于更新i_stream的数据由i_ck_stream传入。input_clock_Update函数的调用位于es_out.c:2324行,该段代码用于设置input_clock_t对象的pcr值,上层传入的命令是ES_OUT_SET_GROUP_PCR,传入此命令的函数只有一个ts.c:2173行的PCRHandle。

查PCRHandle的代码可知,pcr的计算是直接从ts包中获取adaption字段的pcr数据,按照90kHz的时钟转换为秒,并乘以1000000换算成微秒,传递给input_clock_Update,到此完成了i_stream_duration的计算。

3、i_buffering_duration的计算:

在EsOutDecodersStopBuffering中,i_buffering_duration是一个es_out_sys_t对象的i_pts_delay属性再加上另外几个参数来确定。这里我只研究了i_pts_delay的获取,在我的测试中,其余几个值均为0。

es_out_sys_t对象是EsOutDecodersStopBuffering的es_out_t型参数out传入的,回溯代码的调用过程,EsOutDecodersStopBuffering <-EsOutControlLocked <-EsOutControl <-es_out_vaControl <-es_out_control <-CmdExecuteControl,在这里out换成了另一个es_out_t型参数p_out,继续回溯,CmdExecutedControl <-ControlLocked < -Control <-es_out_vaControl <-es_out_Control <-PCRHandle,这里的p_out是demux_t型参数p_demux的成员,PCRHandle <-GatherPES <-Demux <-demux_Demux <-MainLoopDemux,这里的p_demux是input_thread_t型对象p_input成员,再回溯,MainLoopDemux <-MainLoop <-Run,p_input在input.c:550行通过Init函数初始化。

再读Init部分代码,可以发现在input.c:1258行InitSourceInit函数后,i_pts_delay的值发生变化,往下深入,会发现在input.c:2644行,有一个ACCESS_GET_PTS_DELAY操作,最终对应到我的测试中是udp.c:173行,VLC获取了一个叫做:network-caching参数的值,这个值配置的是1000,我猜测应该是ms,返回时又乘以了1000,转换为微秒,准备与i_stream_duration值进行比较。

总结:

这次测试只做了基于udp的组播播放,其它协议可能还有许多细节与udp不同,等到遇到时再进行分析。

读了许久的TS协议,在实际应用中才发现许多东西跟想像的都不同,脱离实际的空想终究是不能成事的。

VLC这个基于PCR的缓冲长度的机制对于我解决不同步的问题,虽没有大的帮助,但应用到播放不同码率的网络串流方面,我想会有一些作用。假设我们开固定大小的缓冲,由于数据传输效率上的问题,经常会遇到解码器缓冲区上溢或下溢的问题,但如果我采用基于时间的缓冲,应该会有一定的改善,只是不知这种分析实时PCR值的方法是否引入了又一个瓶颈。

VLC接收网络串流缓冲时间的计算 (转)的更多相关文章

  1. 两个VLC实现播放串流测试

    实现原理: 一个VLC打开视频文件发布串流(格式HTTP.RTP.RTSP等),另一个VLC打开串流播放 发布串流步骤: 1.菜单“媒体”->“流”,先添加视频文件.选择“串流”,如下图: 2. ...

  2. 两个VLC实现播放串流测试 (转)

    实现原理: 一个VLC打开视频文件发布串流(格式HTTP.RTP.RTSP等),另一个VLC打开串流播放 发布串流步骤: 1.菜单“媒体”->“流”,先添加视频文件.选择“串流”,如下图: 2. ...

  3. 【嵌入式开发】树莓派+官方摄像头模块+VLC串流实时输出网络视频流

    sudo apt-get update sudo apt-get install vlc sudo raspivid -o - -t 0 -w 640 -h 360 -fps 25|cvlc -vvv ...

  4. Windows 11实现直播,VLC超简单实现捕获、串流、播放

    上一篇文章说了搭建Nginx的rtmp服务.实现直播功能 期间发现一个更便捷的工具 VLC media play,官方下载:https://www.videolan.org 1.傻瓜式安装,略过 2. ...

  5. 使用VLC创建组播流

    vlc既是一个播放器,又可以成为一个流媒体服务器.最近需要做udp组播播放相关的东西,需要先在本地搭建一个udp组播服务器,因为机器上本来就装有vlc,所以就用它了. 第一步: 点击媒体->流 ...

  6. 使用VLC推送TS流(纯图版)

    在没有编码器的情况下,可以使用VLC进行推送TS+UDP流 操作步骤如下: 一.UDP方式: 媒体-->流 选用要播放的文件,可以选择多个来播放,选择串流播放 这里直接点击下一步 需要选择在本地 ...

  7. ffmpeg利用libav库把yuv视频流转换为TS串流

    今天到月末了,才发我这个月的第一篇文章,因为这个月前三周一直在看ffmpeg的libavcodec和libavformat两个库源码.实验室要做一个“小传大”的软件,就是android手机或平板电脑的 ...

  8. 调用Live555接收RTSP直播流,转换为Http Live Streaming(iOS直播)协议

    Live555接收RTSP直播流,转换Http Live Streaming(iOS直播)协议 RTSP协议也是广泛使用的直播/点播流媒体协议,之前实现过一个通过live555接收RTSP协议,然后转 ...

  9. -1-4 java io java流 常用流 分类 File类 文件 字节流 字符流 缓冲流 内存操作流 合并序列流

      File类 •文件和目录路径名的抽象表示形式 构造方法 •public File(String pathname) •public File(String parent,Stringchild) ...

随机推荐

  1. 实现C++标准库string类的简单版本

    代码如下: #ifndef STRING_H #define STRING_H #include <cassert> #include <utility> #include & ...

  2. Entity Framework 入门

    Entity Framework的全称是ADO.NET Entity Framework,是微软开发的基于ADO.NET的ORM(Object/Relational Mapping)框架. Entit ...

  3. java并发编程之volatile

    Java语言规范第三版中对volatile的定义如下:Java编程语言允许线程访问共享变量,为了确保共享变量能被准确和一致地更新,线程应该确保通过排他锁单独获得这个变量. 了解volatile关键字之 ...

  4. 第1课 学习C++的意义

    C++是C语言的加强,它们之间并不是对立的关系. 学习C++的优势: 现代软件产品的架构图: 操作系统抽象层:可有可无,但是作为一个移植性好的软件一定需要这一层.这一层的作用就是把操作系统提供的接口做 ...

  5. linux nginx不区别大小写处理方法

    # 把所有的目录及文件名全改成小写,注意之后新增目录及文件只使用小写命名 递归转换目录或文件名方法:python把指定目录下的递归所有目录和文件名转换成小写或大写(http://www.cnblogs ...

  6. bzoj 2839 集合计数——二项式反演

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2839 设 \( g(i) \) 表示至少有 i 个, \( f(i) \) 表示恰好有 i ...

  7. ASP/ASP.NET/VB6文件上传

    1. asp asp 上传文件真的蛋疼,很麻烦,有时候就用第三方组件,或者比较复杂的写法来实现无组件上传. 测试OK的一个叫风声无组件上传类 V2.1 [Fonshen UpLoadClass Ver ...

  8. ETL流程概述及常用实现方法

    ETL流程概述及常用实现方法 http://blog.csdn.net/btkuangxp/article/details/48224187 目录(?)[-] 1抽取作业 1手工开发抽取作业时候的常用 ...

  9. Java-Runoob-高级教程-实例-字符串:03. Java 实例 - 删除字符串中的一个字符

    ylbtech-Java-Runoob-高级教程-实例-字符串:03. Java 实例 - 删除字符串中的一个字符 1.返回顶部 1. Java 实例 - 删除字符串中的一个字符  Java 实例 以 ...

  10. [html][javascript] Cookie

    更多可参考:http://www.cnblogs.com/newsouls/archive/2012/11/12/2766567.html // 读 cookie 方法 function getCoo ...