一、DASH协议


官方文档,包括一些白皮书啊之类的各种:


MPEG-DASH标准第一部分2012版和2014版,英文版


MPEG-DASH官网白皮书


标准文档:


这些白皮书没找到中文版,所以我自己翻译了一下:


MPEG-DASH白皮书第一版翻译


MPEG-DASH白皮书第一部分第二次修订版翻译


MPEG-DASH新功能白皮书翻译


一个比较系统的综述文档MPEG-DASH An Overview


二、DASH相关工具



ITEC给出的一些播放工具和插件


三、DASH协议基本点



图一、MPD文件格式示意图



图二、MPD分层数据模型


MPD文件中的一些关键名词定义(参考白皮书):Periods(区段)、Adaptation Set(AS,自适应子集)、Representation(表示)、Segment(分片)、Subsegment(子分片)。其中一个MPD中包含一个或多个Periods,每个Periods包含一个或多个AS(每个AS对应一组可供切换的码流),一个AS包含一组Representation(每个Representation对应不同的分辨率或码率,保持不变),一个Representation内的内容被切分为多个Segment(方便在不同Segment间切换,粒度小),Segment可以进一步被切分为Subsegment。



<Representation mimeType="video/mp4" 
                   frameRate="24"
                   bandwidth="1558322"
                   codecs="avc1.4d401f" width="1277" height="544">
    <SegmentList duration="10">
        <Initialization sourceURL="http://cdn.bitmovin.net/bbb/video-1500/init.mp4"/>
        <SegmentURL media="http://cdn.bitmovin.net/bbb/video-1500/segment-0.m4s"/>
        <SegmentURL media="http://cdn.bitmovin.net/bbb/video-1500/segment-1.m4s"/>
        <SegmentURL media="http://cdn.bitmovin.net/bbb/video-1500/segment-2.m4s"/>
        <SegmentURL media="http://cdn.bitmovin.net/bbb/video-1500/segment-3.m4s"/>
        <SegmentURL media="http://cdn.bitmovin.net/bbb/video-1500/segment-4.m4s"/>
  </SegmentList>
</Representation>
复制代码




图三、MPD文件示例



转载文章


<!--profiles:不同的profile对应不同的MPD要求和Segment格式要求
mediaPresentationDuration:整个节目的时长
minBufferTime:至少需要缓冲的时间
type:点播对应static,直播对应dynamic
availabilityStartTime="2016-06-28T08:16:57Z":如果是直播流的话,则必须提供,代表MPD中所有Seg从该时间开始可以request了
minimumUpdatePeriod="PT10H":至少每隔这么长时间,MPD就有可能更新一次,只用于直播流-->
<MPD xmlns="urn:mpeg:DASH:schema:MPD:2011" xmlns:ytdrm="http://youtube.com/ytdrm" mediaPresentationDuration="PT0H3M1.63S" minBufferTime="PT1.5S" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011"
type="static">
  <!-- Ad content-->
  <!--duration:Period的时长;start:Period的开始时间-->
  <Period duration="PT30S" start="PT0S">
     <!--BaseURL:相当于根目录,该元素可以在MPD\Period\AdaptationSet\Representation同时出现,若同时出现,则层层嵌套;
     在每一层也可以出现多次,默认使用第一个BaseURL-->
     <BaseURL>ad/</BaseURL>
     <!-- 广告部分的内容可以在720p和1080p之间切换,分别对应两个representation,这两个representation组成一个AdaptationSet;
	几个rep如果要组成一个AS,它们的lang(语言)\contentType\par(宽高比)必须相同;
	segmentAlignment:如果为true,则代表该AS中的segment互不重叠
	startWithSAP:每个Segment的第一帧都是关键帧-->
     <AdaptationSet mimeType="video/mp4" minWidth="1280" par="16:9" contentType="video" maxWidth="1920" minHeight="720" segmentAlignment="true" startWithSAP="1" maxHeight="1080">
         <!-- 720p Representation at 3.2 Mbps;在Representation 层可能出现和AS层重复的属性,以最内层的定义为准-->
         <Representation id="AD720p" bandwidth="3200000" width="1280" height="720" codecs="avc1.640028" mimeType="video/mp4">
             <!--第一种Segment组织形式:BaseURL+SegmentBase;
		适用于每个rep只有一个Seg的情况,往往配合Initialization指定seg初始化信息的byte-range以及indexRange指定Segment index的byterange;
		对于ISO base媒体格式,Initialization部分即对应ftyp+moov这两个box的内容,不能包含任何moof的内容,moov中不能包含media data.关于这些box的含义参见本系列第二篇文章和14496标准;
		对于ISO base媒体格式,Segment Index部分即对应sidx box的内容.标准规定一个Seg又可以切分为多个SubSeg,对应整个Seg的一部分数据,用Segment Index来描述,
		同时,SubSeg还可以进一步切分,即嵌套. 
		sidx box在文件的头部位置,client可以先读取这部分数据,后续就可以只用partial request的方法请求需要的信息,而不用获取全部信息,
		这样的设计主要是为了Seek的方便.实际上通常一个SubSeg就对应一个moof+mdat的内容.
		一个实际的sidx参见本系列第二篇文章和14496标准;
		因为上一个BaseURL的存在,在本示例中的range都对应xxxx.com/ad/720p.mp4这个文件 -->
             <BaseURL>720p.mp4</BaseURL>
             <SegmentBase indexRange="2789-3264">
          	<Initialization range="0-2788" />
             </SegmentBase>
         </Representation>
         <!-- 1080p Representation at 6.8 Mbps -->
         <Representation id="AD1080p" bandwidth="6800000" width="1920" height="1080" codecs="avc1.640028" mimeType="video/mp4">
             <BaseURL>1080p.mp4</BaseURL>
             <SegmentBase indexRange="2755-3230">
          	<Initialization range="0-2754" />
             </SegmentBase>
         </Representation>
     </AdaptationSet>
  </Period>
  <!-- Normal Content -->
  <!--这个Period的开始时间=上一个Period的start+duration-->
  <Period duration="PT0H3M1.63S">
    <!--正片部分的第一个AdaptationSet ,由不同视频码率\分辨率的几个Rep组成-->
    <AdaptationSet mimeType="video/mp4" minWidth="1280" par="16:9" contentType="video" maxWidth="1920" minHeight="720" segmentAlignment="true" startWithSAP="1" maxHeight="1080">
      <!--对AS中媒体内容类型的描述-->	
      <ContentComponent contentType="video" id="1" />
      <!--ContentProtection元素提供了与DRM有关的信息,多个ContentProtection元素即代表当前的DASH内容支持多种DRM方案;
	schemeIdUri属性的内容对应所用DRM方案的uuid值,为了让多种DRM方案可以解密相同的文件,一般都遵循通用加密标准,即CENC,
	在DASH标准中规定cenc对应的schemeIdUri是urn:mpeg:dash:mp4protection:2011,在指明了cenc之后,可以再利用CP元素指定其他的DRM方案,
	具体的uuid-DRM方案对应列表参见http://dashif.org/identifiers/protection/,示例中的edef8ba9-79d6-4ace-a3c8-27dcd51d21ed对应的就是Widevine方案;
	value属性的内容一般是为对应DRM方案提供补充信息的,标准中规定了CENC对应的value值,即schm(scheme type)box中对应的值:cenc. 
	对于其他的DRM方案,它们的一些初始信息一般放在cenc:pssh元素中,其内容对应pssh(protection scheme specific header) box中内容,
	这些信息是BASE64编码的,示例中的内容解码后就可以看到实际包含了contentID和providerID的信息(在本示例中是2015_tears*AUDIO和widevine_test).
	如果是Playready方案,这个pssh中还可能包含了license server的url信息,至于Widevine方案,包括ExoPlayer在内的很多实现都是把license server的url写死在播放器的实现里面的,显然这是一个需要自己做扩展的地方.
	解密内容需要的KID定义在tenc(track encryption) box中,IV定义在senc(Sample Encryption) box中,同时cenc规定的加密算法是AES-CTR,至此,一个DRM系统需要的各种信息基本都有了;
	上面提到的cenc相关内容参见23001-7标准;-->
      <ContentProtection value="cenc" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="7862029a-3d0d-58ea-a4f6-5bdf308646a9"/>
      <ContentProtection schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed">
	<cenc:pssh>
		AAAAR3Bzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAACcIARIBMBoNd2lkZXZpbmVfdGVzdCIKMjAxNV90ZWFycyoFQVVESU8=	
	</cenc:pssh>
      </ContentProtection>
      <Representation bandwidth="4190760" codecs="avc1.4d401f" height="1080" id="1" mimeType="video/mp4" width="1920">
	<!--这次只在Representation 层有BaseURL,于是所有的range都对应xxxx.com/car-cenc-20120827-89.mp4这个文件-->
        <BaseURL>car_cenc-20120827-89.mp4</BaseURL>
        <SegmentBase indexRange="2755-3230">
          <Initialization range="0-2754" />
        </SegmentBase>
      </Representation>
      <Representation bandwidth="2073921" codecs="avc1.4d401f" height="720" id="2" mimeType="video/mp4" width="1280">
	<!--第二种Segment组织形式:(BaseURL)+SegmentList.SegmentList很好理解,就是一个SegmentURL的列表,每一个URL就对应一个可request的Segment;
	    必须指定duration:每个Seg的时长(s);
	    这里指定了一个BaseURL,则每一个SegmentURL实际对应的是xxxx.com/SegmentListExample/segment-1.m4s-->
	<BaseURL>SegmentListExample/</BaseURL>
	<SegmentList duration="2">
	   <!--这里也有一个Initialization元素,它的实际内容也是ftyp+moov-->
           <Initialization sourceURL="car_cenc-20120827-88.mp4"/>
	   <!--每一个SegmentURL对应的media content往往就是sidx+moof+mdat;
		由此我们可以理解这种Seg组织形式与第一种是类似的,只不过把每一个抽象的SubSeg具体的表达出来;
		对于每一个Seg的格式,标准中也有一些要求:每个segment可以包含一个styp box,如果包含了,应该有msdh和msix brand;
		应该包含一个或多个moof+mdat的组合;可以包含一个或多个sidx,需要放在moof之前-->
           <SegmentURL media="segment-1.m4s"/>
           <SegmentURL media="segment-2.m4s"/>
           <SegmentURL media="segment-3.m4s"/>
           <SegmentURL media="segment-4.m4s"/>
           <SegmentURL media="segment-5.m4s"/>
           <SegmentURL media="segment-6.m4s"/>
           <SegmentURL media="segment-7.m4s"/>
           <SegmentURL media="segment-8.m4s"/>
           <SegmentURL media="segment-9.m4s"/>
           <SegmentURL media="segment-10.m4s"/>
        </SegmentList>
      </Representation>
    </AdaptationSet>
    <!--正片部分的第二个AdaptationSet ,由音频Representation 组成,它们的语言都是英语-->
    <AdaptationSet mimeType="audio/mp4" lang="en" startWithSAP="1" contentType="audio" segmentAlignment="true">
      <ContentComponent contentType="audio" id="2" />
      <Representation bandwidth="255236" codecs="mp4a.67.02" id="3" mimeType="audio/mp4" audioSamplingRate="44100" startWithSAP="1">
	<!--声道数,在value中指明-->
	<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
	<!--第三种Segment组织形式:(BaseURL)+SegmentTemplate+SegmentTimeline;
	SegmentTemplate同样可以指定init信息,它的内容依然是ftyp+moov;
	media指定用来生成Segment列表的模板,可以包含的通配符有$RepresentationID$\$Bandwidth$\$Number$\$Time$,
	Number对应Seg的序号,Time对应Seg的起始时间.Time和Number只能取其一.-->
        <SegmentTemplate initialization="audio/en/init.mp4" media="audio/en/seg-$Number$.m4f" startNumber="1" timescale="90000">
	     <!--SegmentTimeline的作用是帮助client知道服务器端有多少个Segment;
		一个SegmentTimeline元素有多个S元素组成,每个S元素包含三个属性:@t(start time)\@r(repeat count)\@d(duration)
		这里的示例表示从时间0开始,有10个Seg,每个Seg的duration是5400000/90000(sec);
		最后得到的实际Seg URL就是xxx.com/audio/en/seg-1.m4f-->
	     <SegmentTimeline>
		<S t="0" r="10" d="5400000"/>
	     </SegmentTimeline>
	</SegmentTemplate>
      </Representation>
      <Representation bandwidth="31749" codecs="mp4a.67.02" id="4" mimeType="audio/mp4" audioSamplingRate="22050" startWithSAP="1">
        <BaseURL>car_cenc-20120827-8b.mp4</BaseURL>
        <SegmentBase indexRange="2673-2932">
          <Initialization range="0-2672" />
        </SegmentBase>
      </Representation>
    </AdaptationSet>
    <!--正片部分的第三个AdaptationSet,也是由音频Representation 组成,但是它们的语言是法语-->
    <AdaptationSet lang="fr" mimeType="audio/mp4" contentType="audio" segmentAlignment="true" startWithSAP="1">
	<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
	<!--第三种Seg组织形式的变体:(BaseURL)+SegmentTemplate+duration-->
	<!--因为init信息不包含实际的媒体内容,所以duration为0-->
	<SegmentTemplate initialization="audio/fr_init.mp4" duration="0"/>
	<Representation id="5" mimeType="audio/mp4" codecs="mp4a.67.02" audioSamplingRate="48000" startWithSAP="1" bandwidth="63008">
		<!--与前一种形式不同,这里没有具体指定每个Seg的duration,而只有一个duration值,
		这个值可能是不精确的,这也是不使用SegmentTimeline的一大劣势.duration(sec)=duration/timescale-->		
		<SegmentTemplate timescale="1000" duration="9941" media="audio/64kbps/redbull_audio_64kbps_segment$Number$.m4s" startNumber="1"/>
	</Representation>
    </AdaptationSet>
  </Period>
</MPD>
复制代码



四、码率自适应协议对比


目前有HLS/DASH/HDS/SSTR(MSSTR/MSS)

协议HLSHDSMSSDASH
公司或组织AppleAdobeMicrosoftMPEG
索引文件m3u/m3u8f4mmrmpd
分片文件tsmp4/f4fmp4mp4/ts
使用Apple及国内很多大型直播国外视频及直播
编码标准H264/AAC,似乎也支持HEVC各种编码方式
延迟相对较小
加密AES-128加密各种加密方式
可伸缩编码支持
分片下载方式单一灵活多样


待补充
https://juejin.im/post/5a697868f265da3e3f4ce17d