HTTP Live Streaming(HLS)是苹果公司提出来的流媒体传输协议。与RTP协议不同的是,HLS可以穿透某些允许HTTP协议通过的防火墙。

一、HLS播放模式

(1) 点播模式(Video on demand, VOD)

点播模式是指当前时间点可以获取到所有index文件和ts文件,二级index文件中记录了所有ts文件的地址。这种模式允许客户端访问全部内容。上面的例子中就是一个点播模式下的m3u8的结构。

(2) 直播模式(Live)

直播模式是指实时生成M3u8和ts文件。它的索引文件一直处于动态变化的,播放的时候需要不断下载二级index文件,以获得最新生成的ts文件播放视频。如果一个二级index文件的末尾没有#EXT-X-ENDLIST标志,说明它是一个Live视频流。

客户端在播放VOD模式的视频时其实只需要下载一次一级index文件和二级index文件就可以得到所有ts文件的下载地址,除非客户端进行比特率切换,否则无需再下载任何index文件,只需顺序下载ts文件并播放就可以了。但是Live模式下略有不同,因为播放的同时,新ts文件也在被生成中,所以客户端实际上是下载一次二级index文件,然后下载ts文件,再下载二级index文件(这个时候这个二级index文件已经被重写,记录了新生成的ts文件的下载地址),再下载新ts文件,如此反复进行播放。

如果HLS的索引文件分为2级,那么第一级的index文件称为Master PlayList,可能包含着各种分辨率的index地址,选定某一个地址后,获取的index文件是第二级,Media PlayList。 保留着每一个#EXT-X-STREAM-INF的下一行是二级index文件的路径,可以用相对路径也可以用绝对路径。这个文件中记录了不同比特率视频流的二级index文件路径,客户端可以自己判断自己的现行网络带宽,来决定播放哪一个视频流。

测试的HLS地址:http://live.hkstv.hk.lxdns.com/live/hks/playlist.m3u8(Live)

http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8(VOD)

二、m3u8文件的格式

在开始流媒体会话时,客户端首先会获取一个m3u8文件,用于获取可以播放的媒体列表。 首先了解m3u8文件中几个标签的含义:

#EXTM3U // m3u文件头,必须放在第一行
#EXTINF // extra info,分片TS的信息,如时长,带宽等
#EXT-X-TARGETDURATION// 指定当前视频流中的切片文件的最大时长
#EXT-X-PLAYLIST-TYPE:VOD // 表示这是一个VOD文件
#EXT-X-ALLOW-CACHE // 是否允许cache
#EXT-X-ENDLIST // m3u8文件结束符

在VLC输入上边VOD测试地址,点击播放后,就会向特定的服务器获取m3u8文件,一个普通的m3u8文件格式如下:

#EXTM3U
#EXT-X-STREAM-INF:PROGRAM-ID=, BANDWIDTH=
gear1/prog_index.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=, BANDWIDTH=
gear2/prog_index.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=, BANDWIDTH=
gear3/prog_index.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=, BANDWIDTH=
gear4/prog_index.m3u8

上述文件表示不同分辨率的m3u8文件地址,获得该文件后,VLC会根据本地带宽选定使用的m3u8文件,然后打印如下日志:

httplive stream debug: bandwidth adaptation detected (program-id=, bandwidth=).
access_http access debug: http: server='devimages.apple.com' port=80 file='/iphone/samples/bipbop/gear1/prog_index.m3u8'

可见,此时VLC选定了bandwidth=200000的选项,然后VLC就会下载该选项对应的m3u8文件,该m3u8文件指定了要下载的ts文件的列表及地址。由于是VOD模式,m3u8文件是全的,最后也有“#EXT-X-ENDLIST”标识。

#EXTM3U
#EXT-X-TARGETDURATION:
#EXT-X-MEDIA-SEQUENCE:
#EXTINF:, no desc
fileSequence0.ts
#EXTINF:, no desc
fileSequence1.ts
#EXTINF:, no desc
fileSequence2.ts
#EXTINF:, no desc
fileSequence3.ts
......
#EXTINF:, no desc
fileSequence178.ts
#EXTINF:, no desc
fileSequence179.ts
#EXTINF:, no desc
fileSequence180.ts
#EXT-X-ENDLIST

三、使用VLC调试HLS协议

在之前的分析中介绍过,播放一个视频通常是access->demux->decoder->render的流水线过程,有时access和demux的过程会合在一起,比如播放RTSP摄像头时,access和demux都在Live555模块内进行。在读取HLS视频流时,access使用的是http+httplive模块,demux模块使用的是libts(之前的分析中有介绍),decoder一般是FFmpeg,render在不同的平台上会使用不同的模块(Windows一般是DShow,Android一般是OpenGL)。了解了播放HLS视频源所使用的模块,可以在对应模块的Open函数中设置断点,调试其模块打开过程,以学习HLS。在modules\access\http.c文件中打印了如下信息:

access_http access debug: http: server='live.hkstv.hk.lxdns.com' port= file='/live/hks/playlist.m3u8'

当点击播放测试的HLS地址后,VLC首先创建了一个access模块(http),http模块主要的工作就是进行http通信,由于通信过程中下载的文件格式是m3u8,因此还需要一个stream filter模块(httplive),也就是说解析m3u8格式是在httplive模块进行的。httplive模块在开启时,会创建hls_Thread线程不断的去下载ts文件,而且如果是实时播放模式的话,还会创建hls_Reload线程去更新ts文件列表。httplive会不断调用http去下载最新的ts文件,下载的ts数据文件中的数据(有视频有音频)保存在httplive模块。在得到了视频音频数据后,接下来要做的就是demux。libts在调用Demux函数在分离时,会调用ReadTSPacket函数,该函数会读取httplive模块下载好的ts数据,将这些ts数据分离至视频和音频FIFO,之后就是视频和音频decoder的事情了,不再赘述。

注意在实时播放模式下,播放HKS实时视频时,获得的ts流地址采用类似滑动窗口的形式,比如,第一次hls_ReloadPlaylist获得的m3u8文件中ts的数字是373363.ts、373364.ts和373365.ts,那么第二次hls_ReloadPlaylist时,获得的m3u8文件中ts的数字就是373364.ts、373365.ts和373366.ts,每次向后加1.

参考资料:

(1) 官方文档:https://github.com/jiayayao/DataSheet/tree/master/stream%20protocol/hls

(2) http://www.jianshu.com/p/426425cad08a

(3) vlc源码分析(四) 调用libts接收TS流

附:

配置好的Windows版vlc工程下载:https://github.com/jiayayao/vlc_2.1.0-vs_2010,下载后使用vs2010可以直接编译运行,调试学习非常方便。

vlc源码分析(七) 调试学习HLS协议的更多相关文章

  1. vlc源码分析(三) 调用live555接收RTSP数据

    首先了解RTSP/RTP/RTCP相关概念,尤其是了解RTP协议:RTP与RTCP协议介绍(转载). vlc使用模块加载机制调用live555,调用live555的文件是live555.cpp. 一. ...

  2. VLC源码分析知识总结

    1.  关于#和## 1.1).在C语言的宏中,#的功能是将其后面的宏参数进行字符串化操作(Stringfication),简单说就是在对它所引用的宏变量通过替换后在其左右各加上一个双引号. 比如在早 ...

  3. JDK1.8源码分析01之学习建议(可以延伸其他源码学习)

    序言:目前有个计划就是准备看一下源码,来提升自己的技术实力.同时现在好多面试官都喜欢问源码,问你是否读过JDK源码等等? 针对如何阅读源码,也请教了我的老师.下面就先来看看老师的回答,也许会有帮助呢. ...

  4. ABP源码分析七:Setting 以及 Mail

    本文主要说明Setting的实现以及Mail这个功能模块如何使用Setting. 首先区分一下ABP中的Setting和Configuration. Setting一般用于需要通过外部配置文件(或数据 ...

  5. vuex 源码分析(七) module和namespaced 详解

    当项目非常大时,如果所有的状态都集中放到一个对象中,store 对象就有可能变得相当臃肿. 为了解决这个问题,Vuex允许我们将 store 分割成模块(module).每个模块拥有自己的 state ...

  6. Vue.js 源码分析(七) 基础篇 侦听器 watch属性详解

    先来看看官网的介绍: 官网介绍的很好理解了,也就是监听一个数据的变化,当该数据变化时执行我们的watch方法,watch选项是一个对象,键为需要观察的数据名,值为一个表达式(函数),还可以是一个对象, ...

  7. vlc源码分析(二) 播放流程

    当点击播放文件或者输入要播放的文件后,vlc会执行一系列的流程. 首先需要了解视频以及流媒体处理及播放的流程,由链接中的描述,视频以及流媒体处理时,首先要解协议(http,rtmp,rtsp等),然后 ...

  8. vlc源码分析(四) 调用libts接收TS流

    代码分析前,先要了解TS流基本概念:TS流之基本概念. VLC解析TS流是通过libts库来分离的,libts库使用libdvbpsi库来解TS表.VLC使用模块加载机制来加载libts库,具体调用的 ...

  9. Heritrix源码分析(七) Heritrix总体介绍(转)

    本博客属原创文章,欢迎转载!转载请务必注明出处:http://guoyunsky.iteye.com/blog/642794         本博客已迁移到本人独立博客: http://www.yun ...

随机推荐

  1. JS基础(四)之jQuery

    31.jQuery(http://jquery.com/)是一个快速.简洁的JavaScript框架. 它封装了JavaScript常用的功能代码,提供一种便捷的JavaScript设计模式,优化HT ...

  2. jQuery基础(工具函数,浏览器信息,检测节点,字符串,$.extend())

    1.获取浏览器的名称与版本信息   在jQuery中,通过$.browser对象可以获取浏览器的名称和版本信息 如$.browser.chrome为true,表示当前为Chrome浏览器, $.bro ...

  3. angualrJs实现图片上传功能

    整体逻辑:service提供FileReader函数,directive提供点击事件的绑定和监听,controller用来修改html上的ng-src属性值 1.HTML <input type ...

  4. L1 Cache, L2 Cache读取命中率与时钟周期计算

    CPU在Cache中找到有用的数据被称为命中,当Cache中没有CPU所需的数据时(这时称为未命中),CPU才访问内存.从理论上讲,在一颗拥有2级Cache的CPU中,读取L1 Cache的命中率为8 ...

  5. U-Push 3.1.5SDK 集成的一些坑

    1.老是mPushAgent.register中onFailure获取不到deviceToken so文件配置有误,需重新配置: PushSDK .x默认只提供armeabi和x86两种so文件夹,若 ...

  6. LeakCanary上传 leak trace 到服务器

    你可以改变处理完成的默认行为,将 leak trace 和 heap dump 上传到你的服务器以便统计分析. 创建一个 LeakUploadService, 最简单的就是继承 DisplayLeak ...

  7. javascript 关于new()继承的笔记

    近期的一些学习总结,如有错误不严谨地方,希望指正! 使用new操作符会有如下操作: 1.创建一个对象temp = {}, 2. temp.__proto__ = A.prototype, 3. A.c ...

  8. 转载:python的编码处理(一)

    以下内容转载自: http://in355hz.iteye.com/blog/1860787 最近业务中需要用 Python 写一些脚本.尽管脚本的交互只是命令行 + 日志输出,但是为了让界面友好些, ...

  9. 铁乐学python_day25_序列化模块

    铁乐学python_day25_序列化模块 部份内容摘自博客http://www.cnblogs.com/Eva-J/ 回顾内置方法: __len__ len(obj)的结果依赖于obj.__len_ ...

  10. ELK搭建实时日志分析平台之一ElasticSearch搭建

    文:铁乐与猫 系统:CentOS Linux release 7.3.1611 (Core) 注:我这里为测试和实验方便,ELK整套都装在同一台服务器环境中了,生产环境的话,可以分开搭建在不同的服务器 ...