ffmpeg 之 dash
在dash 协议出现以前, 各家公司都开发自己的私有流媒体协议,如微软的SS, 苹果的HLS,Adobe 公司的HDS, 3GPP组织的AHS。这给客户端开发者带来了很大的困扰,后由MPEG 组织牵头,参考前几家公司的流媒体协议,共同制定DASH 协议,也称MPEG-DASH,协议标准号为:ISO/IEC23009, 标准共计八部分,其中媒体呈现(MPD)是最重要的一部分,占据正文的70% 以上。关于DASH 协议的演进历史如下图所示。
dash 协议一经推出,就被很多公司接入,有着一统江湖的趋势,除了由MPEG 组织背书外,还与DASH 技术优势由莫大的关系,如下图是dash 协议与其他流媒体协议的比较。
2 mpd 文件分析
1 period 字段
一条完整的mpeg dash stream 可能由一个或者多个period 构成,同一period 内意味着可用媒体内容及其各个可用的码率不会发生变化。直播情况下,需要定期更新MPD 文件。
2 Adaptationset 字段
一个Period 由一个或者多个Adaptationset组成, Adaptationset 由一组可供切换的不同码率的码流组成,这些码流中可能包含一个或者多个media content components。
3 media content component 字段
一个media content component 表示一个不同音视频内容,比如不同语言的音轨属于不同的media content component ,而同一音轨的不同码率属于相同的media content component .
4 Representation 字段
每个Adaptationset 包含一个或者多个Representation , 一个Representation 包含一个或者多个media stream,每个media stream 对应一个media content component, 为了适应不同带宽,dash 网络可能从一个Representation 切换到另一个Representation。
5 Segment 字段
与HLS 协议的segment 一样,每个Representation 由一个或者多个segment 组成, 每个segment 由一个对应的URL 指定,也可能由相同url + 不同的byte range 指定。
MPD 的数据格式组成如下图所示: period - > adaptation -> Representation -> segment
以上就是关于mpd 格式的介绍, 下面我们根据一个原始mpd 文件来分析下mpd 格式内容
3 ffmpeg 对dash 切片
ffmpeg.exe -re -i test.mp4 -codec copy -f dash -window_size 4 -extra_window_size 5 index.mpd
用ffmeg 对音视频进行切片时,它会生成三类文件,mpd + init-stream0/1.mp4 + chunk-streamx-xxxx.mp4 。 其中mpd 用来记录切片的整体信息,init-stream0/1.mp4 相当于MP4文件的moov box , 它记录了当前stream 的metadata信息,还有sps,pps 等等信息。
dash 切片成的格式为fmp4, 可以简单理解成分片化的MP4,是dash 采用的媒体文件格式。普通的MP4 文件由moov + mdat 组成, 而fmp4用 moov + N * segment 组成, segment = moof + mdat。 其中moov 描述文件层次的metadata信息,moof 描述segment 层次metadata 信息。
4 ffmpeg parse mpd 文件
mpd 文件是xml 格式的,具由层次结构,主题里面包含子主题,从上到下,period -> adaptationset -> representation -> segmenttimeline 。由下图可是period 字段除了具有duration 信息,还包含子主题adaptationset 信息,以此类推...., 在parse mpd 文件时,也是从上往下parse.
假设当前有一stream, 具有不同码率video/audio,那么mpd 文件又是如何描述此信息的呢?
stream 用总字段duration , video/audio 用adaptationset 描述,不同码率的video/audio 用representation 描述,在往下是segmenttimeline 代表实际的data.。
5 dash data read
6 dash seek
dash seek 相关code 如下,总结来说就是单一fragment, 和普通片源没差异。 如果是多个fragment 组成的,则需要寻找最靠近的那个fragment ,然后重新建立连接,open 这个fragment。此处有个疑问,假如fragment duration 很长,会不会seek 不精准?
7 总结
从宏观角度看,dash 协议,会将一个stream 切成很多不同码率的segment ,我们parse 出相应的segment ,然后建立网络连接,去读取相应的segment 就好了,当然牵涉如何具体实现,不会这么简单。回看HLS 协议,其实他们两做法很相似,切片,然后去请求这些切片数据。
原文链接:https://blog.csdn.net/DMC111qwf/article/details/114778182