这里是微软的官方介绍,mss和hls出现都比较久了,应用的也非常多。
1、微软SmoothStreamIndexing协议规定了四种消息:
(The IIS Smooth StreamIndexing Transport Protocol defines four types of messages: )
1.Manifest Request
2.Manifest Response
3.Fragment Request
4.Fragment Response
把HTTP cache proxies 的角色放进去:
不同的client,同样请求同一块fragment,第二次直接从cache返回。
自己搭建了一个SS web server,抓包看了一下消息的内容,以BigBuckBunny举例吧。抓包软件最开始用的wireshark,可是不知道为什么总是收不到本来期望能收到的包,后来改用Windows network monitor,很容易上手很好用,还会列出哪些消息是在哪些进程里面。
1. Manifest request
在浏览器中输入http://[server_name]/[virtual_addr]/bigbuckbunny.ism/manifest,client向server发送HTTP请求。
协议中要求的(manifest/fragment request):HTTP方法必须是GET,HTTP协议版本必须是HTTP/1.1
2. Manifest response
Server 将bigbuckbunny.ismc 发回给client,可以在浏览器中显示出来。(用了另外的URL展示)
协议中要求的(manifest/fragment response):HTTP 状态码必须是200,HTTP协议版本必须是HTTP/1.1。payload中就是ismc文件的内容了。
这时如果再次请求(在浏览器中刷新页面),得到的响应却是304:
304 not modified,数据内容跟上一次比没有变化。这个应该跟cache-control的值有关,没研究过不深究了。这篇先不研究manifest文件的具体element和attribute,只看消息交互。
3. Fragment request
在浏览器中输入:http://[server_name]/[virtual_add]/SmoothStreamingPlayer.html
server的响应:
client收到的第一个响应,会是manifest,然后才能根据manifest里面的信息来构建fragment request。
URL里面包含了具体的QualityLevels 和Fragments 值。client向server请求bit rate是2962000,fragments偏移是400000000的video chunk。
4. Fragment response
由于之前已经执行过,播放过了,所以得到的响应时304。Server说还是老数据,自己从cache里面拿吧。
5. Continue
下一个Fragment request 请求的offset是420000000。
终于等到一个不是304的响应。
返回的状态码是200,类型是video/mp4。HTTPPayloadLine是空的,内容包含在下一个响应中:
一般在200 ok响应之后,要接着发好几个带有HTTPPayloadLine的包,见下图,一对一的都是304响应。
用Microsoft Network Monitor 抓包,协议列,请求都是PCCRTP,在wireshark中直接是HTTP。PCCRTP:Peer Content Caching and Retrieval: HTTP extension.
有时候client会收到 412 响应,代表fragment not yet available。
1. Manifest Request
ManifestRequest = [ "/" VirtualPath ] "/" PublishingPointName "." "ism" / VendorExtensionFileExtension "/" "Manifest"
注意上面的式子中有一个斜杠是没有引号的,也就是VendorExtensionFileExtension前面那个,也就是说这个斜杠不是要出现在Request中的,这个斜杠表示或者的意思。
也就是说,"."后面既可以跟ism也可以跟提供商自己的扩展名,"ism"跟VendorExtensionFileExtensions是或的关系。
看来ManifestRequest中必须包含".",就是"/" "Manifest"的前一级必须包含"."。这样看来我自己在lighttpd上搞的目录实际是不符合协议的。
http://ak.xbox.c4assets.com/ondemand/CH4_29_02_29_65973003001001_001_SQ.ism/Manifest
这个URL就是一个Request Manifest。
2. Manifest Response (Manifest 文件的格式)
Manifest文件是个XML文本,遵循XML标准。注:XML 标签对大小写敏感,XML 的属性值须加引号。
Manifest的根元素必须是<SmoothStreamIndexingMedia>,这个元素的意思是“客户端为了播放节目(Presentation)所需的所有元数据”。
这个元素有4个属性:MajorVersion,MinorVersion,TimeScale,Duration。
2011版新加入3个属性:IsLive,LookaheadCount ,DVRWindowLength。这三个属性都是直播相关的。
其中除了TimeScale之外都是必须的,TimeScale之所以不是必须,是因为他有默认值————10000000(1个1,7个0)。
TimeScale的意思是每秒钟Duration属性的增量,Duration就是节目长度的意思。也就是每一秒,Duration加几,TimeScale就是个这数。
可以理解为TimeScale是划分时间的粒度,10000000代表每秒钟节目时长加10的7次方那么多,反过来理解就是,每10的负7次方秒,节目长度就要加1。
默认值把视频划分的够细的啊。(比hls分得更细,hls是官方推荐的10s)
另外两个属性,描述版本用的:MajorVersion必须等于2,MajorVersion必须等于0,这没啥好说的,规定。
这个元素属性挺少的,到这儿就说完了。下边说说这个元素的内容:
内容=[ ProtectionElement S?] 1* StreamIndexElement 注: *元素 表示0或多个元素,1*元素 表示1或多个元素,2*3元素 表示2或3个元素。
上面是协议里写的,翻译成汉语就是,由一个可选的<Protection>元素和若干个<StreamIndex>元素组成。接下来的任务就是看看这俩元素分别是啥了。
先看<StreamIndex>元素。
<StreamIndex>元素的意思“客户端为了播放Stream所需的所有元数据”,跟前边<SmoothStreamIndexingMedia>比,把节目(Presentation)换成了Stream。
其实一个节目一般可以分为两个Stream,即视频流和音频流。以后就管Stream叫“流”了,汉语方便。
这 个元素有以下这12个属 性:Type,Subtype,TimeScale,Name,Chunks,QualityLevels,Url,MaxWidth,MaxHeight,DisplayWidth,DisplayHeight,VendorExtension。
其 中Type是必须的,并且,如果这个<StreamIndex>元素中没有插入<QualityLevel>元素,那么这3个元 素也是必须的:NumberOfFragments, NumberOfTracks,Url。当然,常见的场景是<StreamIndex>元素中都插入 了<QualityLevel>元素。
下边来看看这12个属性都什么意思:
Type:流的类型,可以是video, audio, or text。text有点特殊和不常见,今天先不说。
MaxWidth, MaxHeight, DisplayWidth, DisplayHeight:这4个属性就是字面意思。注意只有当Type属性的值为video时,这4个属性才可以出现。
Subtype:当Type属性的值为text时,这个属性必须出现。这个属性稍微复杂并不常用,今天先不说。
Name :流的名称,没啥好说的。
Chunks :流中Fragment的个数,Fragment就是分片。
QualityLevels :流中Track的个数,目前理解是,一个码率就叫一个Track(对于视频)。协议里说Track元素的名字就是QualityLevel。
Url:客户端用以产生FragmentRequest的格式,这个属性的值必须是UrlPattern:
UrlPattern = QualityLevels("{bitrate}" / "{Bitrate}" ["," "{CustomAttributes}"] )"/"Fragments(TrackName "=" "{start time}" / "{start_time}" )
TimeScale:这个流中的TimeScale,跟前面的TimeScale具有相同的意义。
VendorExtension:内容提供商自己开发扩展用。
下边说说这个元素的内容:
StreamContent = 1*(TrackElement S?) *(StreamFragment S?)
翻译成汉语就是,此元素的内容是一到多个Track元素(<QualityLevel>)与0到多个StreamFragment元素(<c>)组成的。下面正好开始看这两个元素。
<QualityLevel>元素(Track元素)的意思是“客户端为了播放Track所需的所有元数据”,跟前边比,把stream换成了track。
这 个元素有以下这些属 性:Index,Bitrate,MaxWidth,MaxHeight,CodecPrivateData,SamplingRate,Channels,BitsPerSample,PacketSize,AudioTag,NALUnitLengthField
这些属性都是啥意思今天先不说。
这个元素的内容如下:
TrackContent = CustomAttributes?
这个内容协议里描述的没太看明白,而且也不咋重要,今天先不说。
<c>元素(StreamFragment元素)的意思是“分片(Fragments)元数据的集合”。这个元素很重要,今天好好说说。
这个元素有3个属性:n,d,t。其中d和t至少要出现一个。
n:分片在流中的序号,随时间递增。非必须属性。
d:(FragmentDuration)分片的持续时间。由包含这个分片的流的TimeScale属性的值显示的或隐含的指明。如果d属性没有出现,那么他的隐含值要由客户端按如下规则计算:
用本<c>元素的t属性的值减去后面那个<c>元素的t属性的值。翻译成汉语就是,当前分片的开始时间减去后面分片的开时间。
如果一个分片没有后续分片,那么他的d属性隐含值为0.(注:这里协议原文貌似写的有问题,我觉着只有按我这么理解才能解释通)
t:(FragmentTime)分片(开始)时间(点)。由包含这个分片的流的TimeScale属性的值显示的或隐含的指明。如果t属性没有出现,那么他的隐含值要由客户端按如下规则计算:
用本<c>元素前面那个<c>元素的d的值加上t的值。
如果一个分片前面没有其他分片,那么他的t属性隐含值为0.
下边是个例子:
<c t = "0" d = "19680000" />
<c t = "19680000" d="19680000" />
<c t = "39360000" d="19680000" />
为了支持直播,新版协议给视频分片加了两个新的box(type=uiid):tfxdBox(本分片的t和d封装在里面),tfrfBox(下一个或几个分片的t和d封装在里面)。